expression function calls
This commit is contained in:
@@ -200,6 +200,7 @@ public sealed class Generator(List<TypedNodeDefinitionFunc> functions, ModuleGra
|
|||||||
TypedNodeExpressionMemberAccess expression => EmitExpressionMemberAccess(expression),
|
TypedNodeExpressionMemberAccess expression => EmitExpressionMemberAccess(expression),
|
||||||
TypedNodeExpressionLocalIdent expression => expression.Value.Ident,
|
TypedNodeExpressionLocalIdent expression => expression.Value.Ident,
|
||||||
TypedNodeExpressionModuleIdent expression => expression.Value.Ident,
|
TypedNodeExpressionModuleIdent expression => expression.Value.Ident,
|
||||||
|
TypedNodeExpressionFuncCall expression => EmitExpressionFuncCall(expression),
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(node), node, null)
|
_ => throw new ArgumentOutOfRangeException(nameof(node), node, null)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -263,6 +264,13 @@ public sealed class Generator(List<TypedNodeDefinitionFunc> functions, ModuleGra
|
|||||||
return $"{target}.{expression.Name.Ident}";
|
return $"{target}.{expression.Name.Ident}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string EmitExpressionFuncCall(TypedNodeExpressionFuncCall expression)
|
||||||
|
{
|
||||||
|
var name = EmitExpression(expression.Target);
|
||||||
|
var parameterValues = expression.Parameters.Select(EmitExpression).ToList();
|
||||||
|
return $"{name}({string.Join(", ", parameterValues)})";
|
||||||
|
}
|
||||||
|
|
||||||
private string CType(NubType node, string? varName = null)
|
private string CType(NubType node, string? varName = null)
|
||||||
{
|
{
|
||||||
return node switch
|
return node switch
|
||||||
|
|||||||
@@ -135,23 +135,13 @@ public sealed class Parser(string fileName, List<Token> tokens)
|
|||||||
|
|
||||||
var target = ParseExpression();
|
var target = ParseExpression();
|
||||||
|
|
||||||
if (TryExpectSymbol(Symbol.OpenParen))
|
|
||||||
{
|
|
||||||
var parameters = new List<NodeExpression>();
|
|
||||||
|
|
||||||
while (!TryExpectSymbol(Symbol.CloseParen))
|
|
||||||
parameters.Add(ParseExpression());
|
|
||||||
|
|
||||||
return new NodeStatementFuncCall(TokensFrom(startIndex), target, parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TryExpectSymbol(Symbol.Equal))
|
if (TryExpectSymbol(Symbol.Equal))
|
||||||
{
|
{
|
||||||
var value = ParseExpression();
|
var value = ParseExpression();
|
||||||
return new NodeStatementAssignment(TokensFrom(startIndex), target, value);
|
return new NodeStatementAssignment(TokensFrom(startIndex), target, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new CompileException(Diagnostic.Error("Cannot use expression in statement context unless called as a function or used in assignment").At(fileName, target).Build());
|
return new NodeStatementExpression(TokensFrom(startIndex), target);
|
||||||
}
|
}
|
||||||
|
|
||||||
private NodeExpression ParseExpression(int minPrecedence = -1)
|
private NodeExpression ParseExpression(int minPrecedence = -1)
|
||||||
@@ -273,10 +263,26 @@ public sealed class Parser(string fileName, List<Token> tokens)
|
|||||||
throw new CompileException(Diagnostic.Error("Expected start of expression").At(fileName, Peek()).Build());
|
throw new CompileException(Diagnostic.Error("Expected start of expression").At(fileName, Peek()).Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TryExpectSymbol(Symbol.Period))
|
while (true)
|
||||||
{
|
{
|
||||||
var name = ExpectIdent();
|
if (TryExpectSymbol(Symbol.Period))
|
||||||
expr = new NodeExpressionMemberAccess(TokensFrom(startIndex), expr, name);
|
{
|
||||||
|
var name = ExpectIdent();
|
||||||
|
expr = new NodeExpressionMemberAccess(TokensFrom(startIndex), expr, name);
|
||||||
|
}
|
||||||
|
else if (TryExpectSymbol(Symbol.OpenParen))
|
||||||
|
{
|
||||||
|
var parameters = new List<NodeExpression>();
|
||||||
|
|
||||||
|
while (!TryExpectSymbol(Symbol.CloseParen))
|
||||||
|
parameters.Add(ParseExpression());
|
||||||
|
|
||||||
|
expr = new NodeExpressionFuncCall(TokensFrom(startIndex), expr, parameters);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return expr;
|
return expr;
|
||||||
@@ -574,10 +580,9 @@ public sealed class NodeStatementBlock(List<Token> tokens, List<NodeStatement> s
|
|||||||
public List<NodeStatement> Statements { get; } = statements;
|
public List<NodeStatement> Statements { get; } = statements;
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class NodeStatementFuncCall(List<Token> tokens, NodeExpression target, List<NodeExpression> parameters) : NodeStatement(tokens)
|
public sealed class NodeStatementExpression(List<Token> tokens, NodeExpression expression) : NodeStatement(tokens)
|
||||||
{
|
{
|
||||||
public NodeExpression Target { get; } = target;
|
public NodeExpression Expression { get; } = expression;
|
||||||
public List<NodeExpression> Parameters { get; } = parameters;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class NodeStatementReturn(List<Token> tokens, NodeExpression value) : NodeStatement(tokens)
|
public sealed class NodeStatementReturn(List<Token> tokens, NodeExpression value) : NodeStatement(tokens)
|
||||||
@@ -647,6 +652,12 @@ public sealed class NodeExpressionMemberAccess(List<Token> tokens, NodeExpressio
|
|||||||
public TokenIdent Name { get; } = name;
|
public TokenIdent Name { get; } = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed class NodeExpressionFuncCall(List<Token> tokens, NodeExpression target, List<NodeExpression> parameters) : NodeExpression(tokens)
|
||||||
|
{
|
||||||
|
public NodeExpression Target { get; } = target;
|
||||||
|
public List<NodeExpression> Parameters { get; } = parameters;
|
||||||
|
}
|
||||||
|
|
||||||
public sealed class NodeExpressionLocalIdent(List<Token> tokens, TokenIdent value) : NodeExpression(tokens)
|
public sealed class NodeExpressionLocalIdent(List<Token> tokens, TokenIdent value) : NodeExpression(tokens)
|
||||||
{
|
{
|
||||||
public TokenIdent Value { get; } = value;
|
public TokenIdent Value { get; } = value;
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, Mo
|
|||||||
{
|
{
|
||||||
NodeStatementAssignment statement => CheckStatementAssignment(statement),
|
NodeStatementAssignment statement => CheckStatementAssignment(statement),
|
||||||
NodeStatementBlock statement => CheckStatementBlock(statement),
|
NodeStatementBlock statement => CheckStatementBlock(statement),
|
||||||
NodeStatementFuncCall statement => CheckStatementFuncCall(statement),
|
NodeStatementExpression statement => CheckStatementExpression(statement),
|
||||||
NodeStatementIf statement => CheckStatementIf(statement),
|
NodeStatementIf statement => CheckStatementIf(statement),
|
||||||
NodeStatementReturn statement => CheckStatementReturn(statement),
|
NodeStatementReturn statement => CheckStatementReturn(statement),
|
||||||
NodeStatementVariableDeclaration statement => CheckStatementVariableDeclaration(statement),
|
NodeStatementVariableDeclaration statement => CheckStatementVariableDeclaration(statement),
|
||||||
@@ -85,9 +85,12 @@ public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, Mo
|
|||||||
return new TypedNodeStatementBlock(statement.Tokens, statement.Statements.Select(CheckStatement).ToList());
|
return new TypedNodeStatementBlock(statement.Tokens, statement.Statements.Select(CheckStatement).ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypedNodeStatementFuncCall CheckStatementFuncCall(NodeStatementFuncCall statement)
|
private TypedNodeStatementFuncCall CheckStatementExpression(NodeStatementExpression statement)
|
||||||
{
|
{
|
||||||
return new TypedNodeStatementFuncCall(statement.Tokens, CheckExpression(statement.Target), statement.Parameters.Select(CheckExpression).ToList());
|
if (statement.Expression is not NodeExpressionFuncCall funcCall)
|
||||||
|
throw new CompileException(Diagnostic.Error("Expected statement or function call").At(fileName, statement).Build());
|
||||||
|
|
||||||
|
return new TypedNodeStatementFuncCall(statement.Tokens, CheckExpression(funcCall.Target), funcCall.Parameters.Select(CheckExpression).ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypedNodeStatementIf CheckStatementIf(NodeStatementIf statement)
|
private TypedNodeStatementIf CheckStatementIf(NodeStatementIf statement)
|
||||||
@@ -129,6 +132,7 @@ public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, Mo
|
|||||||
NodeExpressionModuleIdent expression => CheckExpressionModuleIdent(expression),
|
NodeExpressionModuleIdent expression => CheckExpressionModuleIdent(expression),
|
||||||
NodeExpressionIntLiteral expression => CheckExpressionIntLiteral(expression),
|
NodeExpressionIntLiteral expression => CheckExpressionIntLiteral(expression),
|
||||||
NodeExpressionMemberAccess expression => CheckExpressionMemberAccess(expression),
|
NodeExpressionMemberAccess expression => CheckExpressionMemberAccess(expression),
|
||||||
|
NodeExpressionFuncCall expression => CheckExpressionFuncCall(expression),
|
||||||
NodeExpressionStringLiteral expression => CheckExpressionStringLiteral(expression),
|
NodeExpressionStringLiteral expression => CheckExpressionStringLiteral(expression),
|
||||||
NodeExpressionStructLiteral expression => CheckExpressionStructLiteral(expression),
|
NodeExpressionStructLiteral expression => CheckExpressionStructLiteral(expression),
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(node))
|
_ => throw new ArgumentOutOfRangeException(nameof(node))
|
||||||
@@ -311,6 +315,17 @@ public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, Mo
|
|||||||
return new TypedNodeExpressionMemberAccess(expression.Tokens, field.Type, target, expression.Name);
|
return new TypedNodeExpressionMemberAccess(expression.Tokens, field.Type, target, expression.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TypedNodeExpressionFuncCall CheckExpressionFuncCall(NodeExpressionFuncCall expression)
|
||||||
|
{
|
||||||
|
var target = CheckExpression(expression.Target);
|
||||||
|
if (target.Type is not NubTypeFunc funcType)
|
||||||
|
throw new CompileException(Diagnostic.Error($"Cannot invoke function call on type '{target.Type}'").At(fileName, target).Build());
|
||||||
|
|
||||||
|
var parameters = expression.Parameters.Select(CheckExpression).ToList();
|
||||||
|
|
||||||
|
return new TypedNodeExpressionFuncCall(expression.Tokens, funcType.ReturnType, target, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
private TypedNodeExpressionStringLiteral CheckExpressionStringLiteral(NodeExpressionStringLiteral expression)
|
private TypedNodeExpressionStringLiteral CheckExpressionStringLiteral(NodeExpressionStringLiteral expression)
|
||||||
{
|
{
|
||||||
return new TypedNodeExpressionStringLiteral(expression.Tokens, NubTypeString.Instance, expression.Value);
|
return new TypedNodeExpressionStringLiteral(expression.Tokens, NubTypeString.Instance, expression.Value);
|
||||||
@@ -491,6 +506,12 @@ public sealed class TypedNodeExpressionMemberAccess(List<Token> tokens, NubType
|
|||||||
public TokenIdent Name { get; } = name;
|
public TokenIdent Name { get; } = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed class TypedNodeExpressionFuncCall(List<Token> tokens, NubType type, TypedNodeExpression target, List<TypedNodeExpression> parameters) : TypedNodeExpression(tokens, type)
|
||||||
|
{
|
||||||
|
public TypedNodeExpression Target { get; } = target;
|
||||||
|
public List<TypedNodeExpression> Parameters { get; } = parameters;
|
||||||
|
}
|
||||||
|
|
||||||
public sealed class TypedNodeExpressionLocalIdent(List<Token> tokens, NubType type, TokenIdent value) : TypedNodeExpression(tokens, type)
|
public sealed class TypedNodeExpressionLocalIdent(List<Token> tokens, NubType type, TokenIdent value) : TypedNodeExpression(tokens, type)
|
||||||
{
|
{
|
||||||
public TokenIdent Value { get; } = value;
|
public TokenIdent Value { get; } = value;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ func main(): i32 {
|
|||||||
|
|
||||||
let me: test::person = struct test::person { age = 21 name = "Oliver" }
|
let me: test::person = struct test::person { age = 21 name = "Oliver" }
|
||||||
|
|
||||||
|
x = test::do_something(me.name)
|
||||||
test::do_something(me.name)
|
test::do_something(me.name)
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
@@ -5,5 +5,6 @@ struct person {
|
|||||||
name: string
|
name: string
|
||||||
}
|
}
|
||||||
|
|
||||||
func do_something(name: string): void {
|
func do_something(name: string): i32 {
|
||||||
|
return 3
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user