[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.
This commit is contained in:
Anton Myasnikov 2020-08-22 00:27:12 +03:00
parent 1828fd6d46
commit 3037be689b
No known key found for this signature in database
GPG Key ID: FEB685E6DAA0A95F
6 changed files with 379 additions and 564 deletions

View File

@ -1,6 +1,4 @@
const PREC = { const PREC = {
CALL: 300000000,
OR: 0, OR: 0,
AND: 1, AND: 1,
COMPARE: 3, COMPARE: 3,
@ -9,13 +7,9 @@ const PREC = {
MINUS: 6, MINUS: 6,
MUL: 7, MUL: 7,
DIV: 7, DIV: 7,
ATTR: 1, ATTR: 1,
TYPE: 101, TYPE: 101,
LET: 100, LET: 100,
EXPR: 100000000,
CONSTR: 100000,
LAM: 1000,
}; };
const OPS = [ const OPS = [
@ -58,367 +52,25 @@ module.exports = grammar({
name: 'ReasonLigo', name: 'ReasonLigo',
word: $ => $.Keyword, word: $ => $.Keyword,
extras: $ => [$.oneline_comment, $.block_comment, /\s/], extras: $ => [$.oneline_comment, $.block_comment, /\s/, $.attr],
conflicts: $ => [ conflicts: $ =>
[$._fun_type, $.type_application], [[$._expr_term, $._pattern]
[$._pattern, $.tuple_pattern], , [$._expr_term, $.var_pattern]
[$._expr], // TODO: left-precendence is used for tuple_expr, right for nested `let`s , [$.Name, $.TypeName]
[$._exprf], , [$._expr_term, $.module_name]
, [$.annot_pattern, $.let_declaration]
[$.tuple_expr, $.parameters], , [$.lambda, $.tuple_pattern]
[$.record_field, $._accessor], // TODO , [$._expr_term, $.nullary_constr_pattern]
[$.variant], // TODO: some alien stuff , [$.list, $.list_pattern]
[$.sum_type], // TODO: fix in `let_declaration`. , [$._expr_term, $.lhs]
[$.bracket_block], // TODO: same as $.lambda_body , [$._field_name, $.lhs]
[$.type_decl], , [$._expr_term, $.capture]
[$.lambda], , [$.type_string, $._literal]
[$._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],
],
rules: { rules: {
contract: $ => sepBy(optional(';'), field("declaration", $._declaration)), contract: $ => sepBy1(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))),
// ),
),
_declaration: $ => _declaration: $ =>
field("declaration", field("declaration",
@ -426,17 +78,212 @@ module.exports = grammar({
$.type_decl, $.type_decl,
$.let_declaration, $.let_declaration,
$.include, $.include,
$.attr_decl,
) )
), ),
attr_decl: $ => //// EXPRESSIONS ///////////////////////////////////////////////////////////
prec.left(PREC.ATTR,
nseq(brackets( let_declaration: $ => prec.left(PREC.LET, seq(
seq('@', field("name", $.Name)) '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: $ => type_decl: $ =>
seq( seq(
'type', 'type',
@ -446,70 +293,84 @@ module.exports = grammar({
), ),
_type_expr: $ => _type_expr: $ =>
choice(
$._fun_type,
$.sum_type,
$.record_type,
),
_fun_type: $ =>
choice( choice(
$.fun_type, $.fun_type,
$._core_type, $._core_type,
$.type_tuple, $.type_tuple,
$.sum_type,
$.record_type,
$.type_string,
), ),
michelson_tuple: $ => seq(
'(',
$._type_expr,
',',
$.String,
',',
$._type_expr,
',',
$.String,
')',
),
fun_type: $ => fun_type: $ =>
seq( prec.right(8,
field("domain", choice($._core_type, $.type_tuple)), seq(
'=>', field("domain", $._type_expr),
field("codomain", $._fun_type), '=>',
field("codomain", $._type_expr),
),
), ),
_core_type: $ => _core_type: $ =>
choice( choice(
$.type_application, $.type_application,
$.TypeName, $.TypeName,
$.type_string, // $.module_TypeName,
$.module_TypeName,
), ),
module_TypeName: $ => module_TypeName: $ =>
seq( seq(
$.module_name, field("module", $.module_name),
'.', '.',
$.TypeName, field("type", $.TypeName),
), ),
type_application: $ => type_application: $ =>
seq( seq(
field("functor", $._core_type), 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_string: $ => $.String,
type_tuple: $ => type_tuple: $ =>
par(sepBy1(',', field("element", $._type_expr))), par(sepBy1(',', field("element", $._type_expr))),
sum_type: $ => sum_type: $ =>
seq( prec.left(8,
optional('|'), seq(
sepBy1('|', field("variant", $.variant)), optional('|'),
sepBy1('|', field("variant", $.variant)),
),
), ),
variant: $ => variant: $ =>
seq( prec.left(8,
field("constructor", $._constr), seq(
optional(par(field("arguments", $._fun_type))), field("constructor", $.Name_Capital),
optional(par(field("arguments", $._type_expr))),
),
), ),
record_type: $ => record_type: $ =>
seq( block(sepBy(',', field("field", $.field_decl))),
'{',
sepBy(',', field("field", $.field_decl)),
'}',
),
field_decl: $ => field_decl: $ =>
seq( seq(
@ -518,115 +379,75 @@ module.exports = grammar({
field("field_type", $._type_expr), field("field_type", $._type_expr),
), ),
te: $ => choice( //// PATTERNS //////////////////////////////////////////////////////////////
$.lambda,
$._expr, _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: $ => unary_constr_pattern: $ => prec(1, seq(
choice( field("constructor", $.Name_Capital),
$._statement, field("arg", $._pattern),
$._expr, )),
$.fun_call,
$.bracket_block,
),
_annot_fun_call: $ => // Workaround used only in bracket blocks constr_pattern: $ => seq(
par(seq( field("ctor", $.Name_Capital),
$.fun_call, optional(seq(
':',
$._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(
'(', '(',
$._core_pattern, sepBy(',', field("arg", $._pattern)),
optional($._type_annotation),
')', ')',
), )),
),
pattern_list: $ => list__($._pattern), annot_pattern: $ => seq(
pattern_constant: $ => 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( choice(
$.Nat, $.Nat,
$.Int,
$.Bool,
$.Tez,
$.String, $.String,
$.Bytes, $.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, struct_name: $ => $.Name,
var: $ => $.Name, var: $ => $.Name,
module_name: $ => $.Name_Capital, module_name: $ => $.Name_Capital,
_constr: $ => $.Name_Capital,
// TODO: remove
_ident: $ => $.Name, _ident: $ => $.Name,
comment: $ => choice( comment: $ => choice(
@ -676,7 +495,8 @@ module.exports = grammar({
skip: $ => 'skip', skip: $ => 'skip',
rec: $ => 'rec', rec: $ => 'rec',
wildcard: $ => '_', wildcard: $ => '_',
rec: $ => 'rec',
attr: $ => seq('[@@', $.Name, ']'), attr: $ => seq('[@', $.Name, ']'),
} }
}); });

View File

@ -112,7 +112,7 @@ recognise = descent (\_ -> error . show . pp) $ map usingScope
-- -- Expr -- -- Expr
, Descent do , Descent do
boilerplate $ \case boilerplate $ \case
"fun_app" -> Apply <$> field "f" <*> field "x" "fun_app" -> Apply <$> field "f" <*> fields "x"
"index_accessor" -> ListAccess <$> field "box" <*> fields "field" "index_accessor" -> ListAccess <$> field "box" <*> fields "field"
"rec_expr" -> RecordUpd <$> field "subject" <*> fields "field" "rec_expr" -> RecordUpd <$> field "subject" <*> fields "field"
"rec_literal" -> Record <$> fields "field" "rec_literal" -> Record <$> fields "field"

View File

@ -71,11 +71,11 @@ recognise = descent (\_ -> error . show . pp) $ map usingScope
, Descent do , Descent do
boilerplate \case boilerplate \case
"let_expr" -> Let <$> field "locals" <*> field "body" "let_expr" -> Let <$> field "locals" <*> field "body"
"fun_call" -> Apply <$> field "f" <*> field "arguments" "fun_call" -> Apply <$> field "f" <*> fields "arguments"
"par_call" -> Apply <$> field "f" <*> field "arguments" "par_call" -> Apply <$> field "f" <*> fields "arguments"
"projection_call" -> Apply <$> field "f" <*> field "arguments" "projection_call" -> Apply <$> field "f" <*> fields "arguments"
"Some_call" -> Apply <$> field "constr" <*> field "arguments" "Some_call" -> Apply <$> field "constr" <*> fields "arguments"
"constr_call" -> Apply <$> field "constr" <*> field "arguments" "constr_call" -> Apply <$> field "constr" <*> fields "arguments"
"arguments" -> Tuple <$> fields "argument" "arguments" -> Tuple <$> fields "argument"
"unop" -> UnOp <$> field "negate" <*> field "arg" "unop" -> UnOp <$> field "negate" <*> field "arg"
"binop" -> BinOp <$> field "arg1" <*> field "op" <*> field "arg2" "binop" -> BinOp <$> field "arg1" <*> field "op" <*> field "arg2"
@ -183,7 +183,7 @@ recognise = descent (\_ -> error . show . pp) $ map usingScope
-- VarDecl -- VarDecl
, Descent do , Descent do
boilerplate \case boilerplate \case
"param_decl" -> Decl <$> field "access" <*> field "name" <*> field "type" "param_decl" -> Decl <$> field "access" <*> field "name" <*> fieldOpt "type"
_ -> fallthrough _ -> fallthrough
-- Mutable -- Mutable

View File

@ -17,6 +17,9 @@ import Product
-- example = "./contracts/variant.religo" -- example = "./contracts/variant.religo"
-- example = "./contracts/amount.religo" -- example = "./contracts/amount.religo"
-- example = "./contracts/multisig.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/FA1.2.religo"
-- example = "../../../src/test/contracts/multisig.religo" -- example = "../../../src/test/contracts/multisig.religo"
-- example = "../../../src/test/contracts/lambda.religo" -- example = "../../../src/test/contracts/lambda.religo"
@ -32,14 +35,11 @@ import Product
-- example = "./contracts/attributes.religo" -- example = "./contracts/attributes.religo"
-- example = "./contracts/lambda.religo" -- example = "./contracts/lambda.religo"
-- example = "./contracts/arithmetic.religo" -- example = "./contracts/arithmetic.religo"
-- example = "./contracts/letin.religo" -- example = "./contracts/FA2.religo"
-- raw :: IO () -- sample''' :: IO ()
-- raw = toParseTree (Path example) -- sample'''
-- >>= print . pp -- = toParseTree (Path example)
-- sample :: IO ()
-- sample = toParseTree (Path example)
-- >>= runParserM . recognise -- >>= runParserM . recognise
-- >>= print . pp . fst -- >>= print . pp . fst
@ -51,50 +51,46 @@ recognise = descent (\_ -> error . show . pp) $ map usingScope
"contract" -> RawContract <$> fields "declaration" "contract" -> RawContract <$> fields "declaration"
_ -> fallthrough _ -> fallthrough
-- ReasonExpr
, Descent do
boilerplate $ \case
"bracket_block" -> Block <$> fields "statement" <*> fieldOpt "return"
_ -> fallthrough
-- Expr -- Expr
, Descent do , Descent do
boilerplate $ \case boilerplate $ \case
"fun_call" -> Apply <$> field "f" <*> field "arguments" "unary_call" -> UnOp <$> field "negate" <*> field "arg"
"lambda_call" -> Apply <$> field "lambda" <*> field "arguments" -- TODO: maybe a separate apply? "binary_call" -> BinOp <$> field "left" <*> field "op" <*> field "right"
"arguments" -> Tuple <$> fields "argument" "Some_call" -> Apply <$> field "some" <*> fields "argument"
"unary_call" -> UnOp <$> field "negate" <*> field "arg" "apply" -> Apply <$> field "function" <*> fields "argument"
"binary_call" -> BinOp <$> field "left" <*> field "op" <*> field "right" "block" -> Seq <$> fields "statement"
"constructor_call" -> Apply <$> field "constructor" <*> field "parameters" "list" -> List <$> fields "element"
"block" -> Seq <$> fields "statement" "indexing" -> ListAccess <$> field "box" <*> fields "index"
"list_expr" -> List <$> fields "element" "annot_expr" -> Annot <$> field "subject" <*> field "type"
"list_access" -> ListAccess <$> field "name" <*> fields "indexes" "if" -> If <$> field "selector" <*> field "then" <*> fieldOpt "else"
"annot_expr" -> Annot <$> field "subject" <*> field "type" -- TODO: possible support for multiple spreads
"conditional" -> If <$> field "selector" <*> field "then" <*> fieldOpt "else" "record" -> Record <$> fields "assignment"
"record_expr" -> Record <$> fields "assignment" "tuple" -> Tuple <$> fields "item"
"tuple_expr" -> Tuple <$> fields "element" "switch" -> Case <$> field "subject" <*> fields "alt"
"lambda" -> Lambda <$> fields "argument" <*> fieldOpt "type" <*> field "body"
"switch_instr" -> Case <$> field "subject" <*> fields "case" _ -> fallthrough
"lambda" -> Lambda <$> fields "arguments" <*> fieldOpt "lambda_type" <*> field "lambda_body"
_ -> fallthrough
-- Pattern -- Pattern
, Descent do , Descent do
boilerplate $ \case boilerplate $ \case
"constr_pattern" -> IsConstr <$> field "constr" <*> fieldOpt "arguments" "tuple_pattern" -> IsTuple <$> fields "pattern"
"tuple_pattern" -> IsTuple <$> fields "element" "annot_pattern" -> IsAnnot <$> field "subject" <*> field "type"
"cons_pattern" -> IsCons <$> field "head" <*> field "tail" "list_pattern" -> IsList <$> fields "pattern"
"annot_pattern" -> IsAnnot <$> field "subject" <*> field "type" "var_pattern" -> IsVar <$> field "var"
_ -> fallthrough "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 -- Alt
, Descent do , Descent do
boilerplate $ \case boilerplate $ \case
"alt" -> Alt <$> field "pattern" <*> field "body" "alt" -> Alt <$> field "pattern" <*> field "expr"
_ -> fallthrough _ -> fallthrough
-- Record fields -- Record fields
-- TODO: capture and record
, Descent do , Descent do
boilerplate $ \case boilerplate $ \case
"record_field" -> FieldAssignment <$> field "name" <*> field "value" "record_field" -> FieldAssignment <$> field "name" <*> field "value"
@ -127,8 +123,8 @@ recognise = descent (\_ -> error . show . pp) $ map usingScope
, Descent do , Descent do
boilerplate $ \case boilerplate $ \case
"module_qualified" -> QualifiedName <$> field "module" <*> fields "method" "qualified_name" -> QualifiedName <$> field "expr" <*> fields "name"
"struct_qualified" -> QualifiedName <$> field "struct" <*> fields "method" "lhs" -> QualifiedName <$> field "callee" <*> fields "name"
_ -> fallthrough _ -> fallthrough
-- Literal -- Literal
@ -144,24 +140,12 @@ recognise = descent (\_ -> error . show . pp) $ map usingScope
-- Declaration -- Declaration
, Descent do , Descent do
boilerplate $ \case boilerplate $ \case
-- TODO: Current `Let` in ast is untyped -- TODO: We forget "rec" field in let
"let_declaration" -> Var <$> field "binding" <*> fieldOpt "let_type" <*> field "let_value" "let_declaration" -> Var <$> field "binding" <*> fieldOpt "type" <*> field "value"
"type_decl" -> TypeDecl <$> field "type_name" <*> field "type_value" "type_decl" -> TypeDecl <$> field "type_name" <*> field "type_value"
"attr_decl" -> Attribute <$> field "name" "attr_decl" -> Attribute <$> field "name"
_ -> fallthrough _ -> 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 -- Name
, Descent do , Descent do
boilerplate' $ \case boilerplate' $ \case
@ -174,12 +158,19 @@ recognise = descent (\_ -> error . show . pp) $ map usingScope
, Descent do , Descent do
boilerplate $ \case boilerplate $ \case
"fun_type" -> TArrow <$> field "domain" <*> field "codomain" "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" "type_tuple" -> TTuple <$> fields "element"
"record_type" -> TRecord <$> fields "field" "record_type" -> TRecord <$> fields "field"
"sum_type" -> TSum <$> fields "variant" "sum_type" -> TSum <$> fields "variant"
_ -> fallthrough _ -> fallthrough
-- Michelson pair types
, Descent do
boilerplate' $ \case
("type_string", i) -> return $ TString i
_ -> fallthrough
-- Variant -- Variant
, Descent do , Descent do
boilerplate $ \case boilerplate $ \case

View File

@ -358,7 +358,7 @@ instance Collectable xs => Scoped (Product xs) CollectM (LIGO (Product xs)) Bind
_ -> skip _ -> skip
instance Collectable xs => Scoped (Product xs) CollectM (LIGO (Product xs)) VarDecl where 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) Mutable
instance Scoped a CollectM (LIGO a) Type instance Scoped a CollectM (LIGO a) Type

View File

@ -78,7 +78,7 @@ data Parameters it
deriving stock (Functor, Foldable, Traversable) deriving stock (Functor, Foldable, Traversable)
data VarDecl it 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 (Show) via PP (VarDecl it)
deriving stock (Functor, Foldable, Traversable) deriving stock (Functor, Foldable, Traversable)
@ -95,7 +95,8 @@ data Type it
| TVar it -- ^ (Name) | TVar it -- ^ (Name)
| TSum [it] -- ^ [Variant] | TSum [it] -- ^ [Variant]
| TProduct [it] -- ^ [Type] | TProduct [it] -- ^ [Type]
| TApply it [it] -- (Name) [Type] | TApply it [it] -- ^ (Name) [Type]
| TString Text -- ^ (TString)
| TTuple [it] | TTuple [it]
| TOr it it it it | TOr it it it it
| TAnd 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. -- | TODO: break onto smaller types? Literals -> Constant; mapOps; mmove Annots to Decls.
data Expr it data Expr it
= Let it it -- Declaration Expr = Let it it -- Declaration Expr
| Apply it it -- (Expr) [Expr] | Apply it [it] -- (Expr) [Expr]
| Constant it -- (Constant) | Constant it -- (Constant)
| Ident it -- (QualifiedName) | Ident it -- (QualifiedName)
| BinOp it it it -- (Expr) Text (Expr) | BinOp it it it -- (Expr) Text (Expr)
@ -191,6 +192,7 @@ data Pattern it
| IsCons it it -- (Pattern) (Pattern) | IsCons it it -- (Pattern) (Pattern)
| IsAnnot it it -- (Pattern) (Type) -- Semantically `Var` | IsAnnot it it -- (Pattern) (Type) -- Semantically `Var`
| IsWildcard | IsWildcard
| IsSpread it -- (Name)
| IsList [it] -- [Pattern] | IsList [it] -- [Pattern]
| IsTuple [it] -- [Pattern] | IsTuple [it] -- [Pattern]
deriving (Show) via PP (Pattern it) deriving (Show) via PP (Pattern it)
@ -275,7 +277,7 @@ instance Pretty1 Parameters where
instance Pretty1 VarDecl where instance Pretty1 VarDecl where
pp1 = \case 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 instance Pretty1 Mutable where
pp1 = \case pp1 = \case
@ -290,6 +292,7 @@ instance Pretty1 Type where
TSum variants -> sexpr "SUM" variants TSum variants -> sexpr "SUM" variants
TProduct elements -> sexpr "PROD" elements TProduct elements -> sexpr "PROD" elements
TApply f xs -> sop f "$" xs TApply f xs -> sop f "$" xs
TString t -> pp t
TTuple xs -> sexpr "TUPLE" xs TTuple xs -> sexpr "TUPLE" xs
TOr l n r m -> sexpr "OR" [l, n, r, m] TOr l n r m -> sexpr "OR" [l, n, r, m]
TAnd l n r m -> sexpr "AND" [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 instance Pretty1 Expr where
pp1 = \case pp1 = \case
Let decl body -> sexpr "let" [decl, body] Let decl body -> sexpr "let" [decl, body]
Apply f xs -> sexpr "apply" [f, xs] Apply f xs -> sexpr "apply" (f : xs)
Constant constant -> constant Constant constant -> constant
Ident qname -> qname Ident qname -> qname
BinOp l o r -> sop l (ppToText o) [r] BinOp l o r -> sop l (ppToText o) [r]
@ -374,6 +377,7 @@ instance Pretty1 Pattern where
IsCons h t -> sop h "::?" [t] IsCons h t -> sop h "::?" [t]
IsAnnot s t -> sexpr "type?" [s, t] IsAnnot s t -> sexpr "type?" [s, t]
IsWildcard -> "_?" IsWildcard -> "_?"
IsSpread n -> "..." <.> pp n
IsList l -> sexpr "list?" l IsList l -> sexpr "list?" l
IsTuple t -> sexpr "tuple?" t IsTuple t -> sexpr "tuple?" t