From 3037be689b2381892b0d1f39fb75bd055d60c47e Mon Sep 17 00:00:00 2001 From: Anton Myasnikov Date: Sat, 22 Aug 2020 00:27:12 +0300 Subject: [PATCH] [LIGO-27] Fix parameters for lambdas and restructure grammar Problem: It happens that "go to definition" fails with lambda parameters meaning that we do not create proper AST for it. Also we need to restructure grammar so that we can support it in the future. Solution: Restructure grammar to use "param_decl" and ensure that we use proper fields for parser resolution. --- .../squirrel/grammar/reasonligo/grammar.js | 814 +++++++----------- tools/lsp/squirrel/src/AST/Camligo/Parser.hs | 2 +- .../lsp/squirrel/src/AST/Pascaligo/Parser.hs | 12 +- .../lsp/squirrel/src/AST/Reasonligo/Parser.hs | 99 +-- tools/lsp/squirrel/src/AST/Scope.hs | 2 +- tools/lsp/squirrel/src/AST/Skeleton.hs | 14 +- 6 files changed, 379 insertions(+), 564 deletions(-) diff --git a/tools/lsp/squirrel/grammar/reasonligo/grammar.js b/tools/lsp/squirrel/grammar/reasonligo/grammar.js index 4ba1ffcc7..bfd4ec0b4 100644 --- a/tools/lsp/squirrel/grammar/reasonligo/grammar.js +++ b/tools/lsp/squirrel/grammar/reasonligo/grammar.js @@ -1,6 +1,4 @@ const PREC = { - - CALL: 300000000, OR: 0, AND: 1, COMPARE: 3, @@ -9,13 +7,9 @@ const PREC = { MINUS: 6, MUL: 7, DIV: 7, - ATTR: 1, TYPE: 101, LET: 100, - EXPR: 100000000, - CONSTR: 100000, - LAM: 1000, }; const OPS = [ @@ -58,367 +52,25 @@ module.exports = grammar({ name: 'ReasonLigo', word: $ => $.Keyword, - extras: $ => [$.oneline_comment, $.block_comment, /\s/], + extras: $ => [$.oneline_comment, $.block_comment, /\s/, $.attr], - conflicts: $ => [ - [$._fun_type, $.type_application], - [$._pattern, $.tuple_pattern], - [$._expr], // TODO: left-precendence is used for tuple_expr, right for nested `let`s - [$._exprf], - - [$.tuple_expr, $.parameters], - [$.record_field, $._accessor], // TODO - [$.variant], // TODO: some alien stuff - [$.sum_type], // TODO: fix in `let_declaration`. - [$.bracket_block], // TODO: same as $.lambda_body - [$.type_decl], - [$.lambda], - [$._instruction, $._expr], // switch_instr - [$._functional_block, $.bracket_block], // TODO: remove - [$.list_access], // TODO: remove - [$.list_access, $._ident], // TODO - [$.record_field, $._ident], // TODO - [$._core_pattern, $._expr], //TODO: remove as soon as possible - [$.lambda_call], // TODO: remove - [$.lambda_call, $.binary_call], - [$._expr, $.bracket_block], // TODO - [$.lambda_call, $.parameters], // TODO - [$["-"], $.negate], // unary vs binary calls - - [$.parameters, $.annot_expr], // TODO - [$.type_tuple, $._core_type], - - [$._pattern, $.annot_pattern], // TODO: constr (pat) case - [$.annot_expr, $._type_annotation], - [$.annot_expr, $.lambda_call], - [$.annot_expr, $._functional_block], - - // TODO: those are produced in conflicts of `fun_call` and `expr` in bracket blocks - [$.annot_expr, $._exprf], - [$.lambda_call, $._exprf], - [$.bracket_block, $._exprf], - [$._functional_block, $._exprf], - [$.tuple_expr, $._exprf], - [$._annot_fun_call, $._exprf], - ], + conflicts: $ => + [[$._expr_term, $._pattern] + , [$._expr_term, $.var_pattern] + , [$.Name, $.TypeName] + , [$._expr_term, $.module_name] + , [$.annot_pattern, $.let_declaration] + , [$.lambda, $.tuple_pattern] + , [$._expr_term, $.nullary_constr_pattern] + , [$.list, $.list_pattern] + , [$._expr_term, $.lhs] + , [$._field_name, $.lhs] + , [$._expr_term, $.capture] + , [$.type_string, $._literal] + ], rules: { - contract: $ => sepBy(optional(';'), field("declaration", $._declaration)), - - _expr: $ => - prec(PREC.EXPR, - seq( - choice( - $.lambda_call, - $.tuple_expr, - $._literal, - // $.fun_call, - $.constructor_call, - $.unary_call, - $.binary_call, - $.annot_expr, - $.list_expr, - $.record_expr, - $._ref, - $._ident, - $.switch_instr, - ), - ), - ), - - // TODO: workaround to move `fun_call` out of `expr` needed in bracket blocks - _exprf: $ => choice($.fun_call, $._expr), - - _annot_expr: $ => - par($.annot_expr), - - annot_expr: $ => - seq( - field("subject", $._expr), - ':', - field("type", $._type_expr), - ), - - // TODO: same as tuple_pattern - // TODO: to annotate expression we do not need to enclose it in brackets - // TODO: possible ((a : p) : q, b) - tuple_expr: $ => - par(sepBy1(',', - seq( - field("element", choice( - $.annot_expr, - $.fun_call, - $._expr, - )), - ) - )), - - constructor_call: $ => - prec(PREC.CONSTR, - seq( - field("constructor", - choice( - $._constr, - $.module_qualified, - ), - ), - field("parameters", $.parameters), - ), - ), - - lambda_call: $ => - seq( - par(field("lambda", $.lambda)), - repeat1( - choice( - field("arguments", $._expr), - par(field("arguments", $.lambda)) - ) - ), // TODO: workaround to move lambda out of expr - ), - - fun_call: $ => - prec.right(PREC.CALL, - seq( - field("f", $.Name), // TODO: may be qualified - field("arguments", $.parameters), - ) - ), - - binary_call: $ => choice( - ...OPS - .map(([op, precendence]) => - prec.left(precendence, seq( - field("left", $._exprf), - field("op", $[op]), - field("right", $._exprf), - )) - ) - ), - - // Workaround to make operators to be instructions as well - // so that they won't be stripped when naming them as fields - ...OPS.reduce( - (acc, [e, _]) => ({ ...acc, [e]: $ => seq(e) }), {} - ), - - unary_call: $ => prec.right(8, - seq( - field("negate", $.negate), - field("arg", $._exprf) - ) - ), - - negate: $ => choice('-', '!'), - - // TODO: refactor - call: $ => - prec.left(1, - choice( - seq($.call, par($._expr)), - par($._expr), - ), - ), - - switch_instr: $ => - prec.left(0, // TODO - seq( - 'switch', - choice( - field('subject', $.Name), - par(field('subject', $._exprf)), - ), - block(seq( - optional('|'), - sepBy1('|', field('case', $.alt)), - )), - ), - ), - - // TODO: it may parse expr with ';' attached to the end - alt: $ => - seq( - field("pattern", $._pattern), - '=>', - field("body", $._functional_block), - optional(';'), - ), - - - _literal: $ => - choice( - $.Nat, - $.Int, - $.Bool, - $.Tez, - $.String, - $.Bytes, - $.Unit, - $.Nil, - $.wildcard, - ), - - record_expr: $ => - seq( - block(seq( - sepBy1(',', field("assignment", choice( - $.spread, - $.record_field, - ))), - optional($._ident), // TODO: not need to be here - )) - ), - - spread: $ => seq( - '...', - field("name", $._ident), // TODO: may be possible expression - ), - - record_field: $ => - seq( - field("name", sepBy1('.', $.Name)), - ':', - field("value", $._expr), - ), - - _statement: $ => choice( - $._instruction, - ), - - _instruction: $ => - prec(PREC.EXPR, choice( - $.conditional, - $.switch_instr, - $.let_declaration, - )), - - lambda: $ => - seq( - field("lambda_head", seq( - field("arguments", $.parameters), - optional(seq(":", - field("lambda_type", - choice($._core_type, $.type_tuple), - ), - )) - )), - '=>', - field("lambda_body", $._functional_block) - ), - - parameters: $ => - par( - sepBy(',', field("parameter", seq( - choice($._exprf, $.lambda), // TODO: workaround to move lambda our of expr - optional($._type_annotation), // TODO: move it somewhere - ))) - ), - - _pattern: $ => - choice( - $.cons_pattern, - $.annot_pattern, - $._core_pattern, - ), - - cons_pattern: $ => - brackets( - seq( - field("head", $._core_pattern), - ',', - field("tail", choice( - $.spread, - $._pattern, - )), - ) - ), - - annot_pattern: $ => - par( - seq( - field("subject", $._core_pattern), - ':', - field("type", $._type_expr), - ) - ), - - _core_pattern: $ => - prec.right(PREC.CONSTR, - seq( - choice( - $.constr_pattern, - $.tuple_pattern, - $._literal, - $.Name, - ), - ) - ), - - tuple_pattern: $ => - par(tuple(field("element", $._pattern))), - - constr_pattern: $ => - prec.right(PREC.CONSTR, // TODO: left precendence fails - seq( - field("constr", $._constr), - optional( - opar( - field("arguments", $._pattern) - ), - )), - ), - - list_expr: $ => brackets( - sepBy(',', field("element", choice( - $.spread, - $._expr, - ))) - ), - - - conditional: $ => - prec.left(PREC.LET, - seq( - 'if', - par(field("selector", $._expr)), - field("then", $.bracket_block), - optional(seq( - 'else', - field("else", $.bracket_block), - )), - ), - ), - - _ref: $ => - choice( - $.module_qualified, - $.struct_qualified, - $._constr, - $.list_access, - ), - - module_qualified: $ => - seq( - field("module", $._constr), - nseq(seq('.', field("method", $.Name))), // TODO: capital letters - ), - - // TODO: may be the same as `list_access` - struct_qualified: $ => - seq( - field("struct", $.Name), - nseq(seq('.', field("method", $._accessor))), - ), - - _accessor: $ => choice($.Name, $.Int), - - list_access: $ => - // prec.left(8, - seq( - field("name", $.Name), - repeat1(brackets(field("indexes", $.Int))), - // ), - ), + contract: $ => sepBy1(optional(';'), field("declaration", $._declaration)), _declaration: $ => field("declaration", @@ -426,17 +78,212 @@ module.exports = grammar({ $.type_decl, $.let_declaration, $.include, - $.attr_decl, ) ), - attr_decl: $ => - prec.left(PREC.ATTR, - nseq(brackets( - seq('@', field("name", $.Name)) - )) + //// EXPRESSIONS /////////////////////////////////////////////////////////// + + let_declaration: $ => prec.left(PREC.LET, seq( + 'let', + optional(field("rec", $.rec)), + sepBy1(',', field("binding", $._pattern)), + optional(seq( + ':', + field("type", $._type_expr) + )), + '=', + field("value", $._expr), + )), + + var_pattern: $ => field("var", $.Name), + + fun_type: $ => + prec.right(8, + seq( + field("domain", $._type_expr), + '=>', + field("codomain", $._type_expr), + ), ), + module_TypeName: $ => + seq( + $.module_name, + '.', + $.TypeName, + ), + + _expr: $ => choice( + $.lambda, + $.indexing, + $.binary_call, + $.unary_call, + $._expr_term, + $.apply, + $.Some_call, + ), + + Some_call: $ => prec.right(10, seq( + field("some", $.Some), + field("argument", $._expr), + )), + + apply: $ => prec.left(20, seq( + field("function", $._expr), + par(sepBy(',', field("argument", $._expr))), + )), + + _expr_term: $ => choice( + $.block, + $.tuple, + $.list, + $._literal, + $.Name, + $.Name_Capital, + $.qualified_name, + $.if, + $.switch, + $.record, + ), + + record: $ => block( + seq( + // TODO: possible multiple spreads + optional(seq(field("spread", $.spread), ',')), + sepBy(',', field("assignment", $._record_field)), + ), + ), + + _record_field: $ => choice( + $.record_field, + $.capture, + ), + + capture: $ => $.Name, + + record_field: $ => seq( + field("name", $.lhs), + ':', + field("value", $._expr), + ), + + lhs: $ => seq( + optional(seq(field("name", $.Name), '.')), + field("callee", $.Name), + ), + + list: $ => brackets( + sepBy(',', field("element", $._spread_expr)), + ), + + _spread_expr: $ => choice( + $._expr, + $.spread, + ), + + spread: $ => seq( + '...', + $._expr, + ), + + if: $ => seq( + 'if', + field("selector", $._expr), + field("then", $.block), + optional(seq( + 'else', + field('else', $.block), + )) + ), + + switch: $ => seq( + 'switch', + field("subject", $._expr_term), + block(seq( + optional('|'), + sepBy('|', field("alt", $.alt)), + )) + ), + + alt: $ => seq( + field("pattern", $._pattern), + '=>', + field("expr", $._expr), + optional(';'), + ), + + qualified_name: $ => seq( + field("expr", $._expr), + '.', + field("name", $.Name), + ), + + binary_call: $ => choice( + ...OPS + .map(([op, precendence]) => + prec.right(precendence, seq( + field("left", $._expr), + field("op", $[op]), + field("right", $._expr), + )) + ) + ), + + // Workaround to make operators to be statements as well + // so that they won't be stripped when naming them as fields + ...OPS.reduce( + (acc, [e, _]) => ({ ...acc, [e]: $ => seq(e) }), {} + ), + + unary_call: $ => prec.right(8, seq(field("negate", $.negate), field("arg", $._expr_term))), + + negate: $ => choice('-', '!'), + + indexing: $ => prec.right(12, seq( + field("box", $._expr), + brackets( + field("index", $._expr), + ) + )), + + block: $ => prec(1, block( + seq( + sepBy(';', field("statement", $._statement)), + optional(';'), + ) + )), + + _statement: $ => prec(1, choice( + $.let_declaration, + $._expr, + )), + + tuple: $ => + par(sepBy1(',', field("item", $._annot_expr))), + + _annot_expr: $ => choice( + $.annot_expr, + $._expr, + ), + + annot_expr: $ => seq( + field("subject", $._expr), + ':', + field("type", $._type_expr), + ), + + lambda: $ => prec.right(12, seq( + par(sepBy(',', field("argument", $._pattern))), + optional(seq( + ':', + field("type", $._type_expr), + )), + '=>', + field("body", $._expr), + )), + + //// TYPES ///////////////////////////////////////////////////////////////// + type_decl: $ => seq( 'type', @@ -446,70 +293,84 @@ module.exports = grammar({ ), _type_expr: $ => - choice( - $._fun_type, - $.sum_type, - $.record_type, - ), - - _fun_type: $ => choice( $.fun_type, $._core_type, $.type_tuple, + $.sum_type, + $.record_type, + $.type_string, ), + michelson_tuple: $ => seq( + '(', + $._type_expr, + ',', + $.String, + ',', + $._type_expr, + ',', + $.String, + ')', + ), + fun_type: $ => - seq( - field("domain", choice($._core_type, $.type_tuple)), - '=>', - field("codomain", $._fun_type), + prec.right(8, + seq( + field("domain", $._type_expr), + '=>', + field("codomain", $._type_expr), + ), ), _core_type: $ => choice( $.type_application, $.TypeName, - $.type_string, - $.module_TypeName, + // $.module_TypeName, ), module_TypeName: $ => seq( - $.module_name, + field("module", $.module_name), '.', - $.TypeName, + field("type", $.TypeName), ), type_application: $ => seq( field("functor", $._core_type), - par(sepBy(',', field("parameter", $._type_expr))), + field("arguments", $._type_arguments), ), + _type_arguments: $ => choice( + // $.michelson_tuple, + par(sepBy(',', field("argument", $._type_expr))), + ), + type_string: $ => $.String, type_tuple: $ => par(sepBy1(',', field("element", $._type_expr))), sum_type: $ => - seq( - optional('|'), - sepBy1('|', field("variant", $.variant)), + prec.left(8, + seq( + optional('|'), + sepBy1('|', field("variant", $.variant)), + ), ), variant: $ => - seq( - field("constructor", $._constr), - optional(par(field("arguments", $._fun_type))), + prec.left(8, + seq( + field("constructor", $.Name_Capital), + optional(par(field("arguments", $._type_expr))), + ), ), record_type: $ => - seq( - '{', - sepBy(',', field("field", $.field_decl)), - '}', - ), + block(sepBy(',', field("field", $.field_decl))), field_decl: $ => seq( @@ -518,115 +379,75 @@ module.exports = grammar({ field("field_type", $._type_expr), ), - te: $ => choice( - $.lambda, - $._expr, + //// PATTERNS ////////////////////////////////////////////////////////////// + + _pattern: $ => + choice( + $.tuple_pattern, + $._literal, + $.var_pattern, + $.annot_pattern, + $.wildcard, + $.unary_constr_pattern, + $.nullary_constr_pattern, + $.list_pattern, + ), + + nullary_constr_pattern: $ => seq( + field("constructor", $.Name_Capital), ), - _functional_block: $ => - choice( - $._statement, - $._expr, - $.fun_call, - $.bracket_block, - ), + unary_constr_pattern: $ => prec(1, seq( + field("constructor", $.Name_Capital), + field("arg", $._pattern), + )), - _annot_fun_call: $ => // Workaround used only in bracket blocks - par(seq( - $.fun_call, - ':', - $._type_expr, - )), - - bracket_block: $ => - prec.right(1000000, // TODO: precendence - block( - choice( - seq( - sepBy(';', field("statement", choice( - $.constructor_call, - seq( - optional($.attr_decl), - $._statement, - ), - $.fun_call, - // $._expr, // TODO: use only `fun_call` from there, somewhat fails if called directly - ))), - optional(seq( - opar( - field("return", - choice( - $._expr, - seq( // TODO: maybe not all returned function calls need to be annotated - $.fun_call, - ':', - $._type_expr, // TODO: maybe we'll need to annotate fields here, but so far we just return multiple 'return's - ) - ) - ) - ), - optional(';'), - ))), - $.bracket_block, - ), // TODO conflict: _group bracket_block - ) - ), - - let_declaration: $ => - prec.left(PREC.LET, - seq( - 'let', - optional($.rec), - field("binding", choice( - sepBy1(',', $._core_pattern), - )), - optional(seq(':', field("type", $._type_expr))), - '=', - field("let_value", - choice( - $.lambda, - $._functional_block, - ), - ), - ) - ), - - _type_annotation: $ => - seq( - ':', - field("type", $._type_expr) - ), - - pattern_term: $ => - choice( - $.Name, - $.pattern_grouped, - ), - - pattern_grouped: $ => - seq( + constr_pattern: $ => seq( + field("ctor", $.Name_Capital), + optional(seq( '(', - $._core_pattern, - optional($._type_annotation), + sepBy(',', field("arg", $._pattern)), ')', - ), + )), + ), - pattern_list: $ => list__($._pattern), - pattern_constant: $ => + annot_pattern: $ => seq( + field("subject", $._pattern), + ':', + field("type", $._type_expr), + ), + + tuple_pattern: $ => prec(13, par( + sepBy1(',', field("pattern", $._pattern)), + )), + + list_pattern: $ => brackets( + sepBy(',', field("pattern", $._spread_pattern)), + ), + + _spread_pattern: $ => choice( + $.spread_pattern, + $._pattern, + ), + + spread_pattern: $ => seq( + '...', + field("expr", $._pattern), + ), + + _literal: $ => choice( $.Nat, + $.Int, + $.Bool, + $.Tez, $.String, $.Bytes, - $.Int, + $.Unit, + $.Nil, + $.None, ), - pattern_tuple: $ => sepBy1(',', $._construct), - - _construct: $ => - choice( - seq($._constr, nseq($.pattern_term)), - par($.pattern_term), - ), /////////////////////////////////////////// @@ -635,8 +456,6 @@ module.exports = grammar({ struct_name: $ => $.Name, var: $ => $.Name, module_name: $ => $.Name_Capital, - _constr: $ => $.Name_Capital, - // TODO: remove _ident: $ => $.Name, comment: $ => choice( @@ -676,7 +495,8 @@ module.exports = grammar({ skip: $ => 'skip', rec: $ => 'rec', wildcard: $ => '_', + rec: $ => 'rec', - attr: $ => seq('[@@', $.Name, ']'), + attr: $ => seq('[@', $.Name, ']'), } }); \ No newline at end of file diff --git a/tools/lsp/squirrel/src/AST/Camligo/Parser.hs b/tools/lsp/squirrel/src/AST/Camligo/Parser.hs index 62f0baf75..067302a9e 100644 --- a/tools/lsp/squirrel/src/AST/Camligo/Parser.hs +++ b/tools/lsp/squirrel/src/AST/Camligo/Parser.hs @@ -112,7 +112,7 @@ recognise = descent (\_ -> error . show . pp) $ map usingScope -- -- Expr , Descent do boilerplate $ \case - "fun_app" -> Apply <$> field "f" <*> field "x" + "fun_app" -> Apply <$> field "f" <*> fields "x" "index_accessor" -> ListAccess <$> field "box" <*> fields "field" "rec_expr" -> RecordUpd <$> field "subject" <*> fields "field" "rec_literal" -> Record <$> fields "field" diff --git a/tools/lsp/squirrel/src/AST/Pascaligo/Parser.hs b/tools/lsp/squirrel/src/AST/Pascaligo/Parser.hs index c0b88e423..45ed7c400 100644 --- a/tools/lsp/squirrel/src/AST/Pascaligo/Parser.hs +++ b/tools/lsp/squirrel/src/AST/Pascaligo/Parser.hs @@ -71,11 +71,11 @@ recognise = descent (\_ -> error . show . pp) $ map usingScope , Descent do boilerplate \case "let_expr" -> Let <$> field "locals" <*> field "body" - "fun_call" -> Apply <$> field "f" <*> field "arguments" - "par_call" -> Apply <$> field "f" <*> field "arguments" - "projection_call" -> Apply <$> field "f" <*> field "arguments" - "Some_call" -> Apply <$> field "constr" <*> field "arguments" - "constr_call" -> Apply <$> field "constr" <*> field "arguments" + "fun_call" -> Apply <$> field "f" <*> fields "arguments" + "par_call" -> Apply <$> field "f" <*> fields "arguments" + "projection_call" -> Apply <$> field "f" <*> fields "arguments" + "Some_call" -> Apply <$> field "constr" <*> fields "arguments" + "constr_call" -> Apply <$> field "constr" <*> fields "arguments" "arguments" -> Tuple <$> fields "argument" "unop" -> UnOp <$> field "negate" <*> field "arg" "binop" -> BinOp <$> field "arg1" <*> field "op" <*> field "arg2" @@ -183,7 +183,7 @@ recognise = descent (\_ -> error . show . pp) $ map usingScope -- VarDecl , Descent do boilerplate \case - "param_decl" -> Decl <$> field "access" <*> field "name" <*> field "type" + "param_decl" -> Decl <$> field "access" <*> field "name" <*> fieldOpt "type" _ -> fallthrough -- Mutable diff --git a/tools/lsp/squirrel/src/AST/Reasonligo/Parser.hs b/tools/lsp/squirrel/src/AST/Reasonligo/Parser.hs index 9ea74f5d2..f4c8ba355 100644 --- a/tools/lsp/squirrel/src/AST/Reasonligo/Parser.hs +++ b/tools/lsp/squirrel/src/AST/Reasonligo/Parser.hs @@ -17,6 +17,9 @@ import Product -- example = "./contracts/variant.religo" -- example = "./contracts/amount.religo" -- example = "./contracts/multisig.religo" +-- example = "./contracts/arithmetic.religo" +-- example = "./contracts/lambda.religo" +-- example = "./contracts/id.religo" -- example = "../../../src/test/contracts/FA1.2.religo" -- example = "../../../src/test/contracts/multisig.religo" -- example = "../../../src/test/contracts/lambda.religo" @@ -32,14 +35,11 @@ import Product -- example = "./contracts/attributes.religo" -- example = "./contracts/lambda.religo" -- example = "./contracts/arithmetic.religo" --- example = "./contracts/letin.religo" +-- example = "./contracts/FA2.religo" --- raw :: IO () --- raw = toParseTree (Path example) --- >>= print . pp - --- sample :: IO () --- sample = toParseTree (Path example) +-- sample''' :: IO () +-- sample''' +-- = toParseTree (Path example) -- >>= runParserM . recognise -- >>= print . pp . fst @@ -51,50 +51,46 @@ recognise = descent (\_ -> error . show . pp) $ map usingScope "contract" -> RawContract <$> fields "declaration" _ -> fallthrough - -- ReasonExpr - , Descent do - boilerplate $ \case - "bracket_block" -> Block <$> fields "statement" <*> fieldOpt "return" - _ -> fallthrough - - -- Expr , Descent do boilerplate $ \case - "fun_call" -> Apply <$> field "f" <*> field "arguments" - "lambda_call" -> Apply <$> field "lambda" <*> field "arguments" -- TODO: maybe a separate apply? - "arguments" -> Tuple <$> fields "argument" - "unary_call" -> UnOp <$> field "negate" <*> field "arg" - "binary_call" -> BinOp <$> field "left" <*> field "op" <*> field "right" - "constructor_call" -> Apply <$> field "constructor" <*> field "parameters" - "block" -> Seq <$> fields "statement" - "list_expr" -> List <$> fields "element" - "list_access" -> ListAccess <$> field "name" <*> fields "indexes" - "annot_expr" -> Annot <$> field "subject" <*> field "type" - "conditional" -> If <$> field "selector" <*> field "then" <*> fieldOpt "else" - "record_expr" -> Record <$> fields "assignment" - "tuple_expr" -> Tuple <$> fields "element" - - "switch_instr" -> Case <$> field "subject" <*> fields "case" - "lambda" -> Lambda <$> fields "arguments" <*> fieldOpt "lambda_type" <*> field "lambda_body" - _ -> fallthrough + "unary_call" -> UnOp <$> field "negate" <*> field "arg" + "binary_call" -> BinOp <$> field "left" <*> field "op" <*> field "right" + "Some_call" -> Apply <$> field "some" <*> fields "argument" + "apply" -> Apply <$> field "function" <*> fields "argument" + "block" -> Seq <$> fields "statement" + "list" -> List <$> fields "element" + "indexing" -> ListAccess <$> field "box" <*> fields "index" + "annot_expr" -> Annot <$> field "subject" <*> field "type" + "if" -> If <$> field "selector" <*> field "then" <*> fieldOpt "else" + -- TODO: possible support for multiple spreads + "record" -> Record <$> fields "assignment" + "tuple" -> Tuple <$> fields "item" + "switch" -> Case <$> field "subject" <*> fields "alt" + "lambda" -> Lambda <$> fields "argument" <*> fieldOpt "type" <*> field "body" + _ -> fallthrough -- Pattern , Descent do boilerplate $ \case - "constr_pattern" -> IsConstr <$> field "constr" <*> fieldOpt "arguments" - "tuple_pattern" -> IsTuple <$> fields "element" - "cons_pattern" -> IsCons <$> field "head" <*> field "tail" - "annot_pattern" -> IsAnnot <$> field "subject" <*> field "type" - _ -> fallthrough + "tuple_pattern" -> IsTuple <$> fields "pattern" + "annot_pattern" -> IsAnnot <$> field "subject" <*> field "type" + "list_pattern" -> IsList <$> fields "pattern" + "var_pattern" -> IsVar <$> field "var" + "wildcard" -> return IsWildcard + "nullary_constr_pattern" -> IsConstr <$> field "constructor" <*> return Nothing + "unary_constr_pattern" -> IsConstr <$> field "constructor" <*> fieldOpt "arg" + "spread_pattern" -> IsSpread <$> field "expr" + _ -> fallthrough -- Alt , Descent do boilerplate $ \case - "alt" -> Alt <$> field "pattern" <*> field "body" + "alt" -> Alt <$> field "pattern" <*> field "expr" _ -> fallthrough -- Record fields + -- TODO: capture and record , Descent do boilerplate $ \case "record_field" -> FieldAssignment <$> field "name" <*> field "value" @@ -127,8 +123,8 @@ recognise = descent (\_ -> error . show . pp) $ map usingScope , Descent do boilerplate $ \case - "module_qualified" -> QualifiedName <$> field "module" <*> fields "method" - "struct_qualified" -> QualifiedName <$> field "struct" <*> fields "method" + "qualified_name" -> QualifiedName <$> field "expr" <*> fields "name" + "lhs" -> QualifiedName <$> field "callee" <*> fields "name" _ -> fallthrough -- Literal @@ -144,24 +140,12 @@ recognise = descent (\_ -> error . show . pp) $ map usingScope -- Declaration , Descent do boilerplate $ \case - -- TODO: Current `Let` in ast is untyped - "let_declaration" -> Var <$> field "binding" <*> fieldOpt "let_type" <*> field "let_value" + -- TODO: We forget "rec" field in let + "let_declaration" -> Var <$> field "binding" <*> fieldOpt "type" <*> field "value" "type_decl" -> TypeDecl <$> field "type_name" <*> field "type_value" "attr_decl" -> Attribute <$> field "name" _ -> fallthrough - -- Parameters - , Descent do - boilerplate $ \case - "parameters" -> Parameters <$> fields "parameter" - _ -> fallthrough - - -- VarDecl - , Descent do - boilerplate $ \case - "param_decl" -> Decl <$> field "access" <*> field "name" <*> field "type" - _ -> fallthrough - -- Name , Descent do boilerplate' $ \case @@ -174,12 +158,19 @@ recognise = descent (\_ -> error . show . pp) $ map usingScope , Descent do boilerplate $ \case "fun_type" -> TArrow <$> field "domain" <*> field "codomain" - "type_application" -> TApply <$> field "functor" <*> fields "parameter" + "type_application" -> TApply <$> field "functor" <*> fields "argument" "type_tuple" -> TTuple <$> fields "element" "record_type" -> TRecord <$> fields "field" "sum_type" -> TSum <$> fields "variant" _ -> fallthrough + -- Michelson pair types + , Descent do + boilerplate' $ \case + ("type_string", i) -> return $ TString i + _ -> fallthrough + + -- Variant , Descent do boilerplate $ \case diff --git a/tools/lsp/squirrel/src/AST/Scope.hs b/tools/lsp/squirrel/src/AST/Scope.hs index b2d5483e3..3e677ec6b 100644 --- a/tools/lsp/squirrel/src/AST/Scope.hs +++ b/tools/lsp/squirrel/src/AST/Scope.hs @@ -358,7 +358,7 @@ instance Collectable xs => Scoped (Product xs) CollectM (LIGO (Product xs)) Bind _ -> skip instance Collectable xs => Scoped (Product xs) CollectM (LIGO (Product xs)) VarDecl where - after r (Decl _ name ty) = def name (Just ty) Nothing (getElem r) + after r (Decl _ name ty) = def name ty Nothing (getElem r) instance Scoped a CollectM (LIGO a) Mutable instance Scoped a CollectM (LIGO a) Type diff --git a/tools/lsp/squirrel/src/AST/Skeleton.hs b/tools/lsp/squirrel/src/AST/Skeleton.hs index a89ba2b61..6c7392f18 100644 --- a/tools/lsp/squirrel/src/AST/Skeleton.hs +++ b/tools/lsp/squirrel/src/AST/Skeleton.hs @@ -78,7 +78,7 @@ data Parameters it deriving stock (Functor, Foldable, Traversable) data VarDecl it - = Decl it it it -- ^ (Mutable) (Name) (Type) + = Decl it it (Maybe it) -- ^ (Mutable) (Name) (Type) deriving (Show) via PP (VarDecl it) deriving stock (Functor, Foldable, Traversable) @@ -95,7 +95,8 @@ data Type it | TVar it -- ^ (Name) | TSum [it] -- ^ [Variant] | TProduct [it] -- ^ [Type] - | TApply it [it] -- (Name) [Type] + | TApply it [it] -- ^ (Name) [Type] + | TString Text -- ^ (TString) | TTuple [it] | TOr it it it it | TAnd it it it it @@ -115,7 +116,7 @@ data TField it -- | TODO: break onto smaller types? Literals -> Constant; mapOps; mmove Annots to Decls. data Expr it = Let it it -- Declaration Expr - | Apply it it -- (Expr) [Expr] + | Apply it [it] -- (Expr) [Expr] | Constant it -- (Constant) | Ident it -- (QualifiedName) | BinOp it it it -- (Expr) Text (Expr) @@ -191,6 +192,7 @@ data Pattern it | IsCons it it -- (Pattern) (Pattern) | IsAnnot it it -- (Pattern) (Type) -- Semantically `Var` | IsWildcard + | IsSpread it -- (Name) | IsList [it] -- [Pattern] | IsTuple [it] -- [Pattern] deriving (Show) via PP (Pattern it) @@ -275,7 +277,7 @@ instance Pretty1 Parameters where instance Pretty1 VarDecl where pp1 = \case - Decl mutability name ty -> sexpr "decl" [mutability, name, ty] + Decl mutability name ty -> sexpr "decl" [mutability, name, pp ty] instance Pretty1 Mutable where pp1 = \case @@ -290,6 +292,7 @@ instance Pretty1 Type where TSum variants -> sexpr "SUM" variants TProduct elements -> sexpr "PROD" elements TApply f xs -> sop f "$" xs + TString t -> pp t TTuple xs -> sexpr "TUPLE" xs TOr l n r m -> sexpr "OR" [l, n, r, m] TAnd l n r m -> sexpr "AND" [l, n, r, m] @@ -305,7 +308,7 @@ instance Pretty1 ReasonExpr where instance Pretty1 Expr where pp1 = \case Let decl body -> sexpr "let" [decl, body] - Apply f xs -> sexpr "apply" [f, xs] + Apply f xs -> sexpr "apply" (f : xs) Constant constant -> constant Ident qname -> qname BinOp l o r -> sop l (ppToText o) [r] @@ -374,6 +377,7 @@ instance Pretty1 Pattern where IsCons h t -> sop h "::?" [t] IsAnnot s t -> sexpr "type?" [s, t] IsWildcard -> "_?" + IsSpread n -> "..." <.> pp n IsList l -> sexpr "list?" l IsTuple t -> sexpr "tuple?" t