mirror of
https://codeberg.org/ProgramSnail/truffle-lama.git
synced 2025-12-05 22:38:43 +00:00
parser fixes, infix operator sequence parsing node
This commit is contained in:
parent
b60602055b
commit
e022ff03b3
4 changed files with 4029 additions and 3453 deletions
|
|
@ -52,13 +52,14 @@ grammar Lama;
|
|||
import java.util.Optional;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.oracle.truffle.api.RootCallTarget;
|
||||
import com.oracle.truffle.api.source.Source;
|
||||
import com.oracle.truffle.api.strings.TruffleString;
|
||||
import org.programsnail.truffle_lama.LamaLanguage;
|
||||
import org.programsnail.truffle_lama.nodes.LamaExpressionNode;
|
||||
import org.programsnail.truffle_lama.nodes.LamaRootNode;
|
||||
import org.programsnail.truffle_lama.nodes.pattern.LamaPattern;
|
||||
}
|
||||
|
||||
@lexer::header
|
||||
|
|
@ -94,7 +95,7 @@ private static void throwParseError(Source source, int line, int charPositionInL
|
|||
throw new LamaParseError(source, line, col, length, String.format("Error(s) parsing script:%n" + location + message));
|
||||
}
|
||||
|
||||
public static LamaExpressionNode parseLama(LamaLanguage language, Source source) {
|
||||
public static LamaRootNode parseLama(LamaLanguage language, Source source) {
|
||||
LamaLexer lexer = new LamaLexer(CharStreams.fromString(source.getCharacters().toString()));
|
||||
LamaParser parser = new LamaParser(new CommonTokenStream(lexer));
|
||||
lexer.removeErrorListeners();
|
||||
|
|
@ -113,26 +114,28 @@ public static LamaExpressionNode parseLama(LamaLanguage language, Source source)
|
|||
|
||||
lama returns [LamaExpressionNode result]:
|
||||
/* (import_expression)* */
|
||||
scope_expression { $result = $scope_expression.result; }
|
||||
scope_expression[false] { $result = $scope_expression.result; factory.setRootExpr($result); }
|
||||
EOF;
|
||||
|
||||
//import_expression : 'import' UIDENT ';';
|
||||
|
||||
scope_expression returns [LamaExpressionNode result]:
|
||||
definition { $result = $expression.result; }
|
||||
scope_expression[boolean do_scope] returns [LamaExpressionNode result]
|
||||
: { if (do_scope) { factory.enterScope(); } }
|
||||
(definition { $result = $expression.result; }
|
||||
(
|
||||
definition { $result = factory.createSeqNode($result, $expression.result); }
|
||||
)* (
|
||||
expression { $result = factory.createSeqNode($result, $expression.result); }
|
||||
)?
|
||||
| expression { $result = $expression.result; }
|
||||
| expression { $result = $expression.result; })
|
||||
{ if (do_scope) { factory.exitScope(); } }
|
||||
;
|
||||
|
||||
definition returns [LamaExpressionNode result]:
|
||||
variable_definition { $result = $variable_definition.result; }
|
||||
| function_definition { $result = $function_definition.result; }
|
||||
;
|
||||
// | infix_definition;
|
||||
// | infix_definition { $result = $infix_definition.result; };
|
||||
|
||||
//
|
||||
|
||||
|
|
@ -144,32 +147,42 @@ variable_definition returns [LamaExpressionNode result]
|
|||
variable_definition_sequence[is_public] { $result = $variable_definition_sequence.result; }
|
||||
;
|
||||
variable_definition_sequence[boolean is_public] returns [LamaExpressionNode result]:
|
||||
variable_definition_item { $result = factory.createVarNode($variable_definition_item.name, $variable_definition_item.expr); }
|
||||
variable_definition_item { $result = factory.createAssignVarNode($variable_definition_item.name, $variable_definition_item.expr); }
|
||||
(','
|
||||
variable_definition_item { $result = factory.createSeqNode($result, factory.createVarNode($variable_definition_item.name, $variable_definition_item.expr)); }
|
||||
variable_definition_item { $result = factory.createSeqNode($result, factory.createAssignVarNode($variable_definition_item.name, $variable_definition_item.expr)); }
|
||||
)* ';';
|
||||
variable_definition_item returns [TruffleString name, Optional<LamaExpressionNode> expr]
|
||||
: { $expr = Optional.empty(); }
|
||||
variable_definition_item returns [Token name, LamaExpressionNode expr]
|
||||
: { $expr = null; }
|
||||
LIDENT { $name = $LIDENT; }
|
||||
('='
|
||||
basic_expression { $expr = Optional.of($basic_expression.result); }
|
||||
basic_expression { $expr = $basic_expression.result; }
|
||||
)?;
|
||||
function_definition returns [LamaExpressionNode result] // TODO: scopes
|
||||
: { boolean is_public = false; }
|
||||
function_definition returns [LamaExpressionNode result]
|
||||
: {
|
||||
boolean is_public = false;
|
||||
List<Token> args = new ArrayList<Token>();
|
||||
factory.enterScope(LamaNodeFactory.LexicalScope.Kind.FUNCTION);
|
||||
}
|
||||
(
|
||||
'public' { is_public = true; }
|
||||
)? 'fun' LIDENT '(' (function_arguments)? ')' function_body
|
||||
{ $result = factory.defineFunction($LIDENT, $function_arguments.args, $function_body.result); }
|
||||
)? 'fun' LIDENT '(' (
|
||||
function_arguments { args = $function_arguments.args; factory.addFunctionArguments(args); }
|
||||
)? ')' function_body
|
||||
{
|
||||
$result = factory.createClosureNode($LIDENT, $function_body.result, args.size()); // create lambda for the function
|
||||
factory.exitScope(); // TODO: create exit node to create vars ??
|
||||
$result = factory.createAssignVarNode($LIDENT, $result); // create global function: out of the created scope
|
||||
}
|
||||
;
|
||||
function_arguments returns [List<TruffleString> args]
|
||||
: { $args = new ArrayList<TruffleString>(); }
|
||||
function_arguments returns [List<Token> args]
|
||||
: { $args = new ArrayList<Token>(); }
|
||||
LIDENT { $args.addLast($LIDENT); }
|
||||
(','
|
||||
LIDENT { $args.addLast($LIDENT); }
|
||||
)*;
|
||||
function_body returns [LamaExpressionNode result]:
|
||||
'{'
|
||||
scope_expression { $result = $scope_expression.result; }
|
||||
scope_expression[true] { $result = $scope_expression.result; }
|
||||
'}';
|
||||
|
||||
//
|
||||
|
|
@ -185,14 +198,14 @@ expression returns [LamaExpressionNode result]:
|
|||
basic_expression { $result = $basic_expression.result; }
|
||||
(';'
|
||||
expression { $result = factory.createSeqNode($result, $expression.result); }
|
||||
)?; // TODO: additional things, exit scope ??
|
||||
)?;
|
||||
basic_expression returns [LamaExpressionNode result]: binary_expression { $result = $binary_expression.result; };
|
||||
binary_expression returns [LamaExpressionNode result]:
|
||||
postfix_expression { $result = $postfix_expression.result; }
|
||||
(
|
||||
any_infix
|
||||
postfix_expression { $result = factory.createBinopNode($any_infix.result, $result, $postfix_expression.result); }
|
||||
)*;
|
||||
)*; // TODO: replace with custom sequence parser (with infixity)
|
||||
postfix_expression returns [LamaExpressionNode result]
|
||||
: { boolean with_minus = false; }
|
||||
(
|
||||
|
|
@ -202,14 +215,24 @@ postfix_expression returns [LamaExpressionNode result]
|
|||
(
|
||||
postfix {
|
||||
if ($postfix.access_index.isPresent()) {
|
||||
$result = factory.createElemNode($result, ($postfix.access_index.get())); // TODO: or RefElem node
|
||||
$result = factory.createElemValueNode($result, $postfix.access_index.get());
|
||||
// TODO: choose between elem and ref
|
||||
} else {
|
||||
$result = factory.createCallNode($result, $postfix.args);
|
||||
}
|
||||
}
|
||||
)*; // TODO: elem or elem ref for access node ??
|
||||
)*
|
||||
{
|
||||
if (with_minus) {
|
||||
$result = factory.createBinopNode(
|
||||
$MINUS,
|
||||
factory.createValueConstNode($MINUS, 0),
|
||||
$result);
|
||||
}
|
||||
}
|
||||
;
|
||||
postfix returns [List<LamaExpressionNode> args, Optional<LamaExpressionNode> access_index]
|
||||
: { $args = new ArrayList<LamaExpressionNode>(); $access_index = Option.empty(); }
|
||||
: { $args = new ArrayList<LamaExpressionNode>(); $access_index = Optional.empty(); }
|
||||
'('
|
||||
expression { $args.addLast($expression.result); }
|
||||
(','
|
||||
|
|
@ -218,7 +241,7 @@ postfix returns [List<LamaExpressionNode> args, Optional<LamaExpressionNode> acc
|
|||
')'
|
||||
| '(' ')'
|
||||
| '['
|
||||
expression { $access_index = Option.of($expression.result); }
|
||||
expression { $access_index = Optional.of($expression.result); }
|
||||
']'
|
||||
;
|
||||
|
||||
|
|
@ -226,14 +249,25 @@ primary returns [LamaExpressionNode result]:
|
|||
DECIMAL_LITERAL { $result = factory.createConstNode($DECIMAL_LITERAL); } // minus - inside decimal literal definition
|
||||
| STRING_LITERAL { $result = factory.createStringNode($STRING_LITERAL); }
|
||||
| CHAR_LITERAL { $result = factory.createCharConstNode($CHAR_LITERAL); }
|
||||
| LIDENT { $result = factory.createRefNode($LIDENT); }
|
||||
| LIDENT { $result = factory.createValueNode($LIDENT); } // TODO: choose between value and ref
|
||||
| tok='true' { $result = factory.createValueConstNode($tok, 1); }
|
||||
| tok='false' { $result = factory.createValueConstNode($tok, 0); }
|
||||
| 'infix' any_infix { $result = factory.createRefNode($any_infix.result); }
|
||||
| 'fun' '(' function_arguments ')' function_body
|
||||
{ $result = factory.createClosureNode($function_arguments.args, $function_body.result); } // TODO: scopes
|
||||
| 'skip' { $result = factory.createSkipNode(); }
|
||||
| '(' scope_expression ')' { $result = $scope_expression.result; } // add some scope for correct attribution ??
|
||||
| 'infix' any_infix { $result = factory.createValueNode($any_infix.result); }
|
||||
| tok='fun' '('
|
||||
{
|
||||
List<Token> args = new ArrayList<Token>();
|
||||
factory.enterScope(LamaNodeFactory.LexicalScope.Kind.INNER_CLOSURE);
|
||||
}
|
||||
function_arguments { args = $function_arguments.args; factory.addFunctionArguments(args); }
|
||||
// TODO: make optional ??
|
||||
')'
|
||||
function_body
|
||||
{
|
||||
$result = factory.createClosureNode($tok, $function_body.result, args.size());
|
||||
factory.exitScope(); // TODO: create exit node to create vars ??
|
||||
}
|
||||
| tok='skip' { $result = factory.createSkipNode($tok); }
|
||||
| '(' scope_expression[true] ')' { $result = $scope_expression.result; } // TODO: check
|
||||
| list_expression { $result = $list_expression.result; }
|
||||
| array_expression { $result = $array_expression.result; }
|
||||
| s_expression { $result = $s_expression.result; }
|
||||
|
|
@ -282,27 +316,31 @@ s_expression returns [LamaExpressionNode result]
|
|||
|
||||
if_expression returns [LamaExpressionNode result]
|
||||
: { LamaExpressionNode do_else = null; }
|
||||
'if' expression 'then' scope_expression (
|
||||
'if' expression 'then' scope_expression[true]
|
||||
(
|
||||
else_part { do_else = $else_part.result; }
|
||||
)? 'fi'
|
||||
{ $result = factory.createIfNode($expression.result, $scope_expression.result, do_else); }
|
||||
;
|
||||
else_part returns [LamaExpressionNode result]:
|
||||
'elif' { LamaExpressionNode do_else = null; } expression 'then' scope_expression (
|
||||
'elif' { LamaExpressionNode do_else = null; } expression 'then' scope_expression[true] (
|
||||
else_part { do_else = $else_part.result; }
|
||||
)? { $result = factory.createIfNode($expression.result, $scope_expression.result, do_else); }
|
||||
| 'else' scope_expression { $result = $scope_expression.result; };
|
||||
| 'else' scope_expression[true] { $result = $scope_expression.result; };
|
||||
|
||||
//
|
||||
|
||||
while_do_expression returns [LamaExpressionNode result]: 'while' expression 'do' scope_expression 'od'
|
||||
while_do_expression returns [LamaExpressionNode result]: 'while' expression 'do' scope_expression[true] 'od'
|
||||
{ $result = factory.createWhileNode($expression.result, $scope_expression.result); };
|
||||
do_while_expression returns [LamaExpressionNode result]: 'do' scope_expression 'while' expression 'od'
|
||||
do_while_expression returns [LamaExpressionNode result]: 'do' scope_expression[true] 'while' expression 'od'
|
||||
{ $result = factory.createDoWhileNode($expression.result, $scope_expression.result); };
|
||||
for_expression returns [LamaExpressionNode result]:
|
||||
'for' init=scope_expression ',' cond=expression ',' inc=expression 'do' expr=scope_expression 'od'
|
||||
// TODO: add scope, etc.
|
||||
{ $result = factory.createSeqNode($init.result, factory.createWhileNode($cond.result, factory.createSeqNode($expr.result, $inc.result))); }
|
||||
'for' { factory.enterScope(); }
|
||||
init=scope_expression[false] ',' cond=expression ',' inc=expression 'do' expr=scope_expression[true] 'od'
|
||||
{
|
||||
$result = factory.createSeqNode($init.result, factory.createWhileNode($cond.result, factory.createSeqNode($expr.result, $inc.result)));
|
||||
factory.exitScope();
|
||||
}
|
||||
;
|
||||
|
||||
//
|
||||
|
|
@ -311,7 +349,7 @@ pattern returns [LamaPattern result]:
|
|||
cons_pattern { $result = $cons_pattern.result; }
|
||||
| simple_pattern { $result = $simple_pattern.result; }
|
||||
;
|
||||
cons_pattern returns [LamaPattern result]: simple_pattern ':' pattern { $result = factory.createSexpPattern("cons", {$simple_pattern.result, $pattern.result}); };
|
||||
cons_pattern returns [LamaPattern result]: simple_pattern ':' pattern { $result = factory.createSexpConsPattern($simple_pattern.result, $pattern.result); };
|
||||
simple_pattern returns [LamaPattern result]:
|
||||
wildcard_pattern { $result = $wildcard_pattern.result; }
|
||||
| s_expr_pattern { $result = $s_expr_pattern.result; }
|
||||
|
|
@ -322,16 +360,16 @@ simple_pattern returns [LamaPattern result]:
|
|||
('@'
|
||||
pattern { pat = $pattern.result; }
|
||||
)?
|
||||
{ $result = factory.createNamedPattern($LIDENT, Objects.requireNonNullElse(pat, factory.createWildcardPattern()); }
|
||||
{ $result = factory.createNamedPattern($LIDENT, Objects.requireNonNullElse(pat, factory.createWildcardPattern())); }
|
||||
| { boolean is_negative = false; }
|
||||
(
|
||||
MINUS { is_negative = true; }
|
||||
)?
|
||||
DECIMAL_LITERAL { $result = is_negative ? factory.createNegativeConstPattern($DECIMAL_LITERAL) : factory.createConstPattern($DECIMAL_LITERAL); }
|
||||
| STRING_LITERAL { $result = factory.createStringPattern(LamaStrings.convertStringLiteral($STRING_LITERAL)); }
|
||||
| CHAR_LITERAL { $result = factory.createConstPattern(LamaStrings.convertCharLiteral($CHAR_LITERAL)); }
|
||||
| 'true' { $result = factory.createConstPattern(1); }
|
||||
| 'false' { $result = factory.createConstPattern(0); }
|
||||
| STRING_LITERAL { $result = factory.createStringPattern($STRING_LITERAL); }
|
||||
| CHAR_LITERAL { $result = factory.createConstPattern($CHAR_LITERAL); }
|
||||
| tok='true' { $result = factory.createValueConstPattern($tok, 1); }
|
||||
| tok='false' { $result = factory.createValueConstPattern($tok, 0); }
|
||||
| '#' 'box' { $result = factory.createBoxedPattern(); }
|
||||
| '#' 'val' { $result = factory.createUnBoxedPattern(); }
|
||||
| '#' 'str' { $result = factory.createStringTagPattern(); }
|
||||
|
|
@ -368,7 +406,7 @@ list_pattern returns [LamaPattern result]
|
|||
'{' (
|
||||
pattern { elems.addLast($pattern.result); }
|
||||
(','
|
||||
pattern { elems.addLast($pattern.result); } //FIXME: wrong order
|
||||
pattern { elems.addLast($pattern.result); }
|
||||
)*)?
|
||||
'}'
|
||||
{ $result = factory.createListSexpPattern(elems); }
|
||||
|
|
@ -380,18 +418,20 @@ case_expression returns [LamaExpressionNode result]:
|
|||
'case' expression 'of' case_branches 'esac' { $result = factory.createCaseNode($expression.result, $case_branches.pats, $case_branches.exprs); }
|
||||
;
|
||||
case_branches returns [List<LamaPattern> pats, List<LamaExpressionNode> exprs]
|
||||
: { $pats = new ArrayList<LamaPattern>(); $exprs = new ArrayList<LamaExpressionNode> exprs; }
|
||||
: { $pats = new ArrayList<LamaPattern>(); $exprs = new ArrayList<LamaExpressionNode>(); }
|
||||
case_branch { $pats.addLast($case_branch.pat); $exprs.addLast($case_branch.expr); }
|
||||
('|'
|
||||
case_branch { $pats.addLast($case_branch.pat); $exprs.addLast($case_branch.expr); }
|
||||
)*;
|
||||
case_branch returns [LamaPattern pat, LamaExpressionNode expr]:
|
||||
case_branch returns [LamaPattern pat, LamaExpressionNode expr]
|
||||
: { factory.enterScope(); }
|
||||
pattern { $pat = $pattern.result; }
|
||||
'->'
|
||||
scope_expression { $expr = $scope_expression.result; }
|
||||
scope_expression[false] { $expr = $scope_expression.result; }
|
||||
{ factory.exitScope(); }
|
||||
;
|
||||
|
||||
any_infix returns [String result]:
|
||||
any_infix returns [Token result]:
|
||||
INFIX { $result = $INFIX; }
|
||||
| MINUS { $result = $MINUS; }
|
||||
;
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1,6 +1,5 @@
|
|||
package org.programsnail.truffle_lama.parser;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.frame.FrameDescriptor;
|
||||
import com.oracle.truffle.api.frame.FrameSlotKind;
|
||||
import com.oracle.truffle.api.source.Source;
|
||||
|
|
@ -9,6 +8,7 @@ import org.antlr.v4.runtime.Token;
|
|||
import org.programsnail.truffle_lama.LamaLanguage;
|
||||
import org.programsnail.truffle_lama.LamaStrings;
|
||||
import org.programsnail.truffle_lama.nodes.LamaExpressionNode;
|
||||
import org.programsnail.truffle_lama.nodes.LamaRootNode;
|
||||
import org.programsnail.truffle_lama.nodes.controlflow.LamaCaseNode;
|
||||
import org.programsnail.truffle_lama.nodes.controlflow.LamaDoWhileNode;
|
||||
import org.programsnail.truffle_lama.nodes.controlflow.LamaIfNode;
|
||||
|
|
@ -132,7 +132,7 @@ public class LamaNodeFactory {
|
|||
// ---
|
||||
|
||||
public boolean isGlobal() {
|
||||
return outer == null;
|
||||
return top == null;
|
||||
}
|
||||
|
||||
public boolean isFramed() {
|
||||
|
|
@ -261,31 +261,102 @@ public class LamaNodeFactory {
|
|||
private final Source source;
|
||||
private final TruffleString sourceString;
|
||||
|
||||
/* State while parsing an expr. */
|
||||
private LexicalScope lexicalScope;
|
||||
private final LamaLanguage language;
|
||||
private LamaExpressionNode rootExpr;
|
||||
|
||||
private enum InfixKind {
|
||||
LEFT,
|
||||
RIGHT,
|
||||
NONE,
|
||||
}
|
||||
|
||||
private Map<String, Integer> infixPriorities;
|
||||
private Map<String, InfixKind> infixKinds;
|
||||
|
||||
public LamaNodeFactory(LamaLanguage language, Source source) {
|
||||
this.language = language;
|
||||
this.source = source;
|
||||
this.sourceString = LamaStrings.fromJavaString(source.getCharacters().toString());
|
||||
lexicalScope = new LexicalScope(null, LexicalScope.Kind.FUNCTION); // same to top level
|
||||
this.lexicalScope = new LexicalScope(null, LexicalScope.Kind.FUNCTION); // same to top level
|
||||
|
||||
infixPriorities = new HashMap<>();
|
||||
infixKinds = new HashMap<>();
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
public void enterScope() {
|
||||
enterScope(LexicalScope.Kind.INNER_SCOPE);
|
||||
}
|
||||
|
||||
public void enterScope(LexicalScope.Kind kind) {
|
||||
lexicalScope = new LexicalScope(lexicalScope, kind);
|
||||
}
|
||||
|
||||
public void exitScope() {
|
||||
// TODO: save vars to clear them & create corresponding scope node ??
|
||||
lexicalScope = lexicalScope.getOuter();
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
// TODO: custom infixes: non-0integer indices (at, before, after)
|
||||
// NOTE: very slow implementation, can be optimized
|
||||
LamaExpressionNode createInfixArrayRecursive(List<Token> oprs, List<LamaExpressionNode> exprs) {
|
||||
assert oprs.size() == exprs.size() - 1;
|
||||
|
||||
if (exprs.size() == 1) {
|
||||
return exprs.getFirst();
|
||||
}
|
||||
|
||||
if (exprs.size() == 2) {
|
||||
return createAnyBinopNode(oprs.getFirst(), exprs.getFirst(), exprs.getLast());
|
||||
}
|
||||
|
||||
int splitIndex = 0;
|
||||
{
|
||||
String splitOpr = null;
|
||||
int splitPriority = 0;
|
||||
InfixKind splitKind = null;
|
||||
for (int i = 0; i < oprs.size(); ++i) {
|
||||
String currentSplitOpr = oprs.get(i).getText();
|
||||
if (Objects.equals(splitOpr, currentSplitOpr)) {
|
||||
if (splitKind == InfixKind.RIGHT) { // TODO: check left or right
|
||||
splitIndex = i;
|
||||
continue;
|
||||
}
|
||||
if (splitKind == InfixKind.NONE) {
|
||||
throw new LamaException("Operator '" + splitOpr + "' can't be chained");
|
||||
}
|
||||
}
|
||||
|
||||
Integer currentSplitPriority = infixPriorities.get(currentSplitOpr);
|
||||
if (currentSplitPriority == null) {
|
||||
throw new LamaException("Unknown operator '" + splitOpr + "' (split priority)");
|
||||
}
|
||||
|
||||
if (splitOpr == null || currentSplitPriority > splitPriority) { // TODO: check < or >
|
||||
splitOpr = currentSplitOpr;
|
||||
splitPriority = currentSplitPriority;
|
||||
splitKind = infixKinds.get(splitOpr);
|
||||
if (splitKind == null) {
|
||||
throw new LamaException("Unknown operator '" + splitOpr + "' (split kind)");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LamaExpressionNode leftExpr = createInfixArrayRecursive(oprs.subList(0, splitIndex), exprs.subList(0, splitIndex + 1));
|
||||
LamaExpressionNode rightExpr = createInfixArrayRecursive(oprs.subList(splitIndex + 1, oprs.size()), exprs.subList(splitIndex + 1, exprs.size()));
|
||||
|
||||
return createAnyBinopNode(oprs.get(splitIndex), leftExpr, rightExpr);
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
// TODO: add to parser
|
||||
public void AddFunctionArguments(Token[] args) {
|
||||
public void addFunctionArguments(List<Token> args) {
|
||||
for (Token arg : args) {
|
||||
lexicalScope.addArgument(arg.getText());
|
||||
}
|
||||
|
|
@ -327,7 +398,7 @@ public class LamaNodeFactory {
|
|||
public LamaExpressionNode createVarNode(Token token) {
|
||||
String name = token.getText();
|
||||
|
||||
int slot = lexicalScope.add(name); // TODO: check if not arg ??
|
||||
int slot = lexicalScope.add(name);
|
||||
return addSrcFromToken(lexicalScope.isGlobal() /*global scope*/
|
||||
? new LamaGlobalVarNode(name)
|
||||
: new LamaLocalVarNode(slot), token);
|
||||
|
|
@ -340,6 +411,10 @@ public class LamaNodeFactory {
|
|||
// TODO: fix assignment in parser
|
||||
public LamaExpressionNode createAssignVarNode(Token token, LamaExpressionNode value) {
|
||||
var definition = createVarNode(token);
|
||||
if (value == null) {
|
||||
return definition;
|
||||
}
|
||||
|
||||
var reference = createRefNode(token);
|
||||
var assignment = createAssignNode(reference, value);
|
||||
return createSeqNode(definition, assignment);
|
||||
|
|
@ -353,11 +428,14 @@ public class LamaNodeFactory {
|
|||
public LamaExpressionNode createAnyBinopNode(Token opToken, LamaExpressionNode left, LamaExpressionNode right) {
|
||||
String op = opToken.getText();
|
||||
return switch (op) {
|
||||
// case ":" -> // TODO: cons
|
||||
case ":=" -> createAssignNode(left, right);
|
||||
case "+", "-", "/", "%",
|
||||
"<", "<=", ">", ">=", "==", "!=",
|
||||
"&&", "!!" -> createBinopNode(opToken, left, right);
|
||||
default -> createCallNode(createRefNode(opToken), new LamaExpressionNode[]{left, right});
|
||||
default -> createCallNode(
|
||||
createRefNode(opToken),
|
||||
List.of(new LamaExpressionNode[]{left, right}));
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -366,6 +444,11 @@ public class LamaNodeFactory {
|
|||
return addSrcFromNodes(LamaBinopNodeGen.create(left, right, op), left, right);
|
||||
}
|
||||
|
||||
public LamaExpressionNode createElemValueNode(LamaExpressionNode array, LamaExpressionNode index) {
|
||||
// TODO: replace with separate node for more efficiency
|
||||
return createElemRefOrValueNode(array, index, true);
|
||||
}
|
||||
|
||||
public LamaExpressionNode createElemRefOrValueNode(LamaExpressionNode array, LamaExpressionNode index, boolean doUnref) {
|
||||
return addUnref(createElemRefNode(array, index), doUnref);
|
||||
}
|
||||
|
|
@ -374,8 +457,16 @@ public class LamaNodeFactory {
|
|||
return addSrcFromNodes(LamaElemRefNodeGen.create(array, index), array, index);
|
||||
}
|
||||
|
||||
public LamaExpressionNode createCallNode(LamaExpressionNode func, LamaExpressionNode[] args) {
|
||||
return addSrcFromNodes(new LamaCallNode(func, args), func, args.length > 0 ? args[args.length - 1] : func);
|
||||
public LamaExpressionNode createCallNode(LamaExpressionNode func, List<LamaExpressionNode> args) {
|
||||
return addSrcFromNodes(
|
||||
new LamaCallNode(func, args.toArray(new LamaExpressionNode[0])),
|
||||
func,
|
||||
args.isEmpty() ? func : args.getLast());
|
||||
}
|
||||
|
||||
public LamaExpressionNode createValueNode(Token token) {
|
||||
// TODO: replace with separate node for more efficiency
|
||||
return createRefOrValueNode(token, true);
|
||||
}
|
||||
|
||||
public LamaExpressionNode createRefOrValueNode(Token token, boolean doUnref) {
|
||||
|
|
@ -407,27 +498,28 @@ public class LamaNodeFactory {
|
|||
return addSrcFromToken(new LamaSkipNode(), token);
|
||||
}
|
||||
|
||||
public LamaExpressionNode createArrayNode(LamaExpressionNode[] elems) {
|
||||
LamaExpressionNode result = new LamaArrayNode(elems);
|
||||
return elems.length > 0 ? addSrcFromNodes(result, elems[0], elems[elems.length - 1]) : result;
|
||||
public LamaExpressionNode createArrayNode(List<LamaExpressionNode> elems) {
|
||||
LamaExpressionNode[] elemsArray = elems.toArray(new LamaExpressionNode[0]);
|
||||
LamaExpressionNode result = new LamaArrayNode(elemsArray);
|
||||
return elems.isEmpty() ? result : addSrcFromNodes(result, elems.getFirst(), elems.getLast());
|
||||
}
|
||||
|
||||
// sexps-pairs with tag 'cons'
|
||||
public LamaExpressionNode createListSexpNode(LamaExpressionNode[] elems) {
|
||||
public LamaExpressionNode createListSexpNode(List<LamaExpressionNode> elems) {
|
||||
LamaExpressionNode result = new LamaConstNode(0);
|
||||
for (int i = elems.length - 1; i >= 0; --i) {
|
||||
result = new LamaSexpNode(LamaStrings.fromJavaString("cons"), new LamaExpressionNode[]{elems[i], result});
|
||||
for (int i = elems.size() - 1; i >= 0; --i) {
|
||||
result = new LamaSexpNode(LamaStrings.fromJavaString("cons"), new LamaExpressionNode[]{elems.get(i), result});
|
||||
}
|
||||
return elems.length > 0 ? addSrcFromNodes(result, elems[0], elems[elems.length - 1]) : result;
|
||||
return elems.isEmpty() ? result : addSrcFromNodes(result, elems.getFirst(), elems.getLast());
|
||||
}
|
||||
|
||||
public LamaExpressionNode createSexpNode(Token tag, LamaExpressionNode[] elems) {
|
||||
LamaExpressionNode result = new LamaSexpNode(LamaStrings.fromJavaString(tag.getText()), elems);
|
||||
return elems.length > 0 ? addSrcFromNodes(result, elems[0]/*TODO: use tag instead*/, elems[elems.length - 1]) : addSrcFromToken(result, tag);
|
||||
public LamaExpressionNode createSexpNode(Token tag, List<LamaExpressionNode> elems) {
|
||||
LamaExpressionNode result = new LamaSexpNode(LamaStrings.fromJavaString(tag.getText()), elems.toArray(new LamaExpressionNode[0]));
|
||||
return elems.isEmpty() ? addSrcFromToken(result, tag) : addSrcFromTokenAndNode(result, tag, elems.getLast());
|
||||
}
|
||||
|
||||
public LamaExpressionNode createIfNode(LamaExpressionNode condition, LamaExpressionNode doThen, LamaExpressionNode doElse) {
|
||||
return addSrcFromNodes(new LamaIfNode(condition, doThen, doElse), condition, doElse);
|
||||
return addSrcFromNodes(new LamaIfNode(condition, doThen, doElse), condition, doElse == null ? doThen : doElse);
|
||||
}
|
||||
|
||||
public LamaExpressionNode createWhileNode(LamaExpressionNode condition, LamaExpressionNode body) {
|
||||
|
|
@ -438,10 +530,16 @@ public class LamaNodeFactory {
|
|||
return addSrcFromNodes(new LamaDoWhileNode(condition, body), condition, body);
|
||||
}
|
||||
|
||||
public LamaExpressionNode createCaseNode(LamaExpressionNode value, LamaPattern[] patterns, LamaExpressionNode[] exprs) {
|
||||
assert patterns.length == exprs.length;
|
||||
assert patterns.length > 0;
|
||||
return addSrcFromNodes(new LamaCaseNode(value, patterns, exprs), value, exprs[exprs.length - 1]);
|
||||
public LamaExpressionNode createCaseNode(LamaExpressionNode value, List<LamaPattern> patterns, List<LamaExpressionNode> exprs) {
|
||||
assert patterns.size() == exprs.size();
|
||||
assert !patterns.isEmpty();
|
||||
return addSrcFromNodes(
|
||||
new LamaCaseNode(
|
||||
value,
|
||||
patterns.toArray(new LamaPattern[0]),
|
||||
exprs.toArray(new LamaExpressionNode[0])),
|
||||
value,
|
||||
exprs.getLast());
|
||||
}
|
||||
|
||||
// ---
|
||||
|
|
@ -450,19 +548,23 @@ public class LamaNodeFactory {
|
|||
return new LamaWildcardPattern();
|
||||
}
|
||||
|
||||
public LamaPattern createSexpPattern(Token tag, LamaPattern[] elems) {
|
||||
return new LamaSexpPattern(LamaStrings.fromJavaString(tag.getText()), elems);
|
||||
public LamaPattern createSexpConsPattern(LamaPattern leftElem, LamaPattern rightElem) {
|
||||
return new LamaSexpPattern(LamaStrings.fromJavaString("cons"), new LamaPattern[]{leftElem, rightElem});
|
||||
}
|
||||
|
||||
public LamaPattern createArrayPattern(LamaPattern[] elems) {
|
||||
return new LamaArrayPattern(elems);
|
||||
public LamaPattern createSexpPattern(Token tag, List<LamaPattern> elems) {
|
||||
return new LamaSexpPattern(LamaStrings.fromJavaString(tag.getText()), elems.toArray(new LamaPattern[0]));
|
||||
}
|
||||
|
||||
public LamaPattern createArrayPattern(List<LamaPattern> elems) {
|
||||
return new LamaArrayPattern(elems.toArray(new LamaPattern[0]));
|
||||
}
|
||||
|
||||
// sexps-pairs with tag 'cons'
|
||||
public LamaPattern createListSexpPattern(LamaPattern[] elems) {
|
||||
public LamaPattern createListSexpPattern(List<LamaPattern> elems) {
|
||||
LamaPattern result = new LamaConstPattern(0);
|
||||
for (int i = elems.length - 1; i >= 0; --i) {
|
||||
result = new LamaSexpPattern(LamaStrings.fromJavaString("cons"), new LamaPattern[]{elems[i], result});
|
||||
for (int i = elems.size() - 1; i >= 0; --i) {
|
||||
result = new LamaSexpPattern(LamaStrings.fromJavaString("cons"), new LamaPattern[]{elems.get(i), result});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -473,6 +575,10 @@ public class LamaNodeFactory {
|
|||
return new LamaNamedPattern(frameSlot, pattern);
|
||||
}
|
||||
|
||||
public LamaPattern createValueConstPattern(Token token, long value) {
|
||||
return new LamaConstPattern(value);
|
||||
}
|
||||
|
||||
public LamaPattern createConstPattern(Token token) {
|
||||
return new LamaConstPattern(Long.parseLong(token.getText()));
|
||||
}
|
||||
|
|
@ -547,9 +653,12 @@ public class LamaNodeFactory {
|
|||
|
||||
// ---
|
||||
|
||||
public LamaExpressionNode getRootExpr() {
|
||||
// TODO
|
||||
return null;
|
||||
public void setRootExpr(LamaExpressionNode expr) {
|
||||
this.rootExpr = expr;
|
||||
}
|
||||
|
||||
public LamaRootNode getRootExpr() {
|
||||
return new LamaRootNode(language, this.rootExpr);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue