diff --git a/lib/DhallishGrammar.treetop b/lib/DhallishGrammar.treetop index f6e9c9bb99118b754d0c8e6f87e2f102171d6252..42f7f156ceff405ffb838cef0e3052dc7157c0c1 100644 --- a/lib/DhallishGrammar.treetop +++ b/lib/DhallishGrammar.treetop @@ -342,13 +342,13 @@ grammar DhallishGrammar end rule record_merge_expression - exp:application_expression tail:(space? op:("//\\\\" / "/\\" / "//") space? exp:application_expression)* + exp:application_expression tail:(space? op:("//\\\\" / "⩓" / "/\\" / "∧" / "//" / "⫽") space? exp:application_expression)* { def to_node(ctx) tail.elements.reduce(exp.to_node(ctx)) { |tree, node| - if node.op.text_value == "//\\\\" + if node.op.text_value == "//\\\\" or node.op.text_value == "⩓" Dhallish::Ast::RecordTypeRecursiveMergeNode.new tree, node.exp.to_node(ctx) - elsif node.op.text_value == "/\\" + elsif node.op.text_value == "/\\" or node.op.text_value == "∧" Dhallish::Ast::RecordRecursiveMergeNode.new tree, node.exp.to_node(ctx) else Dhallish::Ast::RecordNonRecursiveMergeNode.new tree, node.exp.to_node(ctx) diff --git a/lib/stdlib.rb b/lib/stdlib.rb index b15335dcc69dbbfae1b090951dbd9d62e0d03847..351c6b4faac851d0fb3069798c09fd366ddbaebf 100644 --- a/lib/stdlib.rb +++ b/lib/stdlib.rb @@ -142,6 +142,43 @@ module Dhallish } types["List/tail"] = list_tail_type + types["List/reverse"] = make_fn_type( + [Types::Type.new(Types::Unresolved.new(:a)), :a], + Types::List.new(Types::Unresolved.new(:a)), + Types::List.new(Types::Unresolved.new(:a))) + globalctx["List/reverse"] = BuiltinFunction.new { |a| + BuiltinFunction.new { |list| list.reverse } + } + + types["List/build"] = make_fn_type( + [Types::Type.new(Types::Unresolved.new(:a)), :a], + make_fn_type( + [Types::Type.new(Types::Unresolved.new(:b)), :b], + make_fn_type(:a, :b, :b), :b, :b), + Types::List.new(Types::Unresolved.new(:a))) + globalctx["List/build"] = BuiltinFunction.new { |a| + BuiltinFunction.new { |f| + cons = BuiltinFunction.new { |x| + BuiltinFunction.new { |list| [x] + list } + } + f.call(Types::List.new(a)).call(cons).call([]) + } + } + + types["List/indexed"] = make_fn_type( + [Types::Type.new(Types::Unresolved.new(:a)), :a], + Types::List.new(Types::Unresolved.new(:a)), + Types::List.new(Types::Record.new({ + "index" => Types::Natural, + "value" => Types::Unresolved.new(:a)}))) + globalctx["List/indexed"] = BuiltinFunction.new { |a| + BuiltinFunction.new { |list| + list.map.with_index { |val, idx| + { "index" => idx, "value" => val } + } + } + } + # Optionals: globalctx["Optional"] = BuiltinFunction.new { |a| Types::Optional.new(a) @@ -171,6 +208,19 @@ module Dhallish } types["Optional/fold"] = optional_fold_type + types["Optional/build"] = make_fn_type( + [Types::Type.new(Types::Unresolved.new(:a)), :a], + make_fn_type([Types::Type.new(Types::Unresolved.new(:b)), :b], + make_fn_type(:a, :b), :b, :b), + Types::Optional.new(Types::Unresolved.new(:a))) + globalctx["Optional/build"] = BuiltinFunction.new { |a| + BuiltinFunction.new { |f| + just = BuiltinFunction.new { |x| x } + f.call(Types::Optional.new(a)).call(just).call(nil) + } + } + + # Naturals: natural_fold_type = make_fn_type( Types::Natural,