Delegates
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
namespace Nub.Lang.Parsing;
|
namespace Nub.Lang;
|
||||||
|
|
||||||
public class FuncParameter(string name, Type type)
|
public class FuncParameter(string name, Type type)
|
||||||
{
|
{
|
||||||
public string Name { get; } = name;
|
public string Name { get; } = name;
|
||||||
public Type Type { get; } = type;
|
public Type Type { get; } = type;
|
||||||
|
|
||||||
|
public override string ToString() => $"{Name}: {Type}";
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,6 @@ func main() {
|
|||||||
write("test");
|
write("test");
|
||||||
}
|
}
|
||||||
|
|
||||||
func write(msg: void) {
|
func write(msg: Func) {
|
||||||
syscall(SYS_WRITE, STD_OUT, msg);
|
syscall(SYS_WRITE, STD_OUT, msg);
|
||||||
}
|
}
|
||||||
@@ -24,6 +24,8 @@ public class Lexer
|
|||||||
[','] = Symbol.Comma,
|
[','] = Symbol.Comma,
|
||||||
['.'] = Symbol.Period,
|
['.'] = Symbol.Period,
|
||||||
['='] = Symbol.Assign,
|
['='] = Symbol.Assign,
|
||||||
|
['<'] = Symbol.LessThan,
|
||||||
|
['>'] = Symbol.GreaterThan,
|
||||||
};
|
};
|
||||||
|
|
||||||
private readonly string _src;
|
private readonly string _src;
|
||||||
@@ -34,7 +36,7 @@ public class Lexer
|
|||||||
_src = src;
|
_src = src;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Token> Lex()
|
public IReadOnlyCollection<Token> Lex()
|
||||||
{
|
{
|
||||||
_index = 0;
|
_index = 0;
|
||||||
List<Token> tokens = [];
|
List<Token> tokens = [];
|
||||||
@@ -79,7 +81,7 @@ public class Lexer
|
|||||||
current = Peek();
|
current = Peek();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LiteralToken(Type.Int32, buffer);
|
return new LiteralToken(new PrimitiveType(PrimitiveTypeKind.Int64), buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Chars.TryGetValue(current.Value, out var charSymbol))
|
if (Chars.TryGetValue(current.Value, out var charSymbol))
|
||||||
@@ -102,7 +104,7 @@ public class Lexer
|
|||||||
buffer += current.Value;
|
buffer += current.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LiteralToken(Type.Pointer, buffer);
|
return new LiteralToken(new PointerType(), buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (char.IsWhiteSpace(current.Value))
|
if (char.IsWhiteSpace(current.Value))
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ public enum Symbol
|
|||||||
CloseBrace,
|
CloseBrace,
|
||||||
OpenBracket,
|
OpenBracket,
|
||||||
CloseBracket,
|
CloseBracket,
|
||||||
|
LessThan,
|
||||||
|
GreaterThan,
|
||||||
Comma,
|
Comma,
|
||||||
Period,
|
Period,
|
||||||
Assign
|
Assign
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
namespace Nub.Lang.Parsing;
|
namespace Nub.Lang.Parsing;
|
||||||
|
|
||||||
public class FuncCallNode(string name, IEnumerable<ExpressionNode> parameters) : StatementNode
|
public class FuncCall(string name, IEnumerable<ExpressionNode> parameters)
|
||||||
{
|
{
|
||||||
public string Name { get; } = name;
|
public string Name { get; } = name;
|
||||||
public IEnumerable<ExpressionNode> Parameters { get; } = parameters;
|
public IEnumerable<ExpressionNode> Parameters { get; } = parameters;
|
||||||
|
|
||||||
|
public override string ToString() => $"{Name}()";
|
||||||
}
|
}
|
||||||
8
Nub.Lang/Nub.Lang/Parsing/FuncCallExpressionNode.cs
Normal file
8
Nub.Lang/Nub.Lang/Parsing/FuncCallExpressionNode.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Nub.Lang.Parsing;
|
||||||
|
|
||||||
|
public class FuncCallExpressionNode(FuncCall funcCall) : ExpressionNode
|
||||||
|
{
|
||||||
|
public FuncCall FuncCall { get; } = funcCall;
|
||||||
|
|
||||||
|
public override string ToString() => FuncCall.ToString();
|
||||||
|
}
|
||||||
6
Nub.Lang/Nub.Lang/Parsing/FuncCallStatementNode.cs
Normal file
6
Nub.Lang/Nub.Lang/Parsing/FuncCallStatementNode.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Nub.Lang.Parsing;
|
||||||
|
|
||||||
|
public class FuncCallStatementNode(FuncCall funcCall) : StatementNode
|
||||||
|
{
|
||||||
|
public FuncCall FuncCall { get; } = funcCall;
|
||||||
|
}
|
||||||
@@ -1,8 +1,13 @@
|
|||||||
namespace Nub.Lang.Parsing;
|
using Nub.Lib;
|
||||||
|
|
||||||
public class FuncDefinitionNode(string name, IEnumerable<FuncParameter> parameters, BlockNode body) : DefinitionNode
|
namespace Nub.Lang.Parsing;
|
||||||
|
|
||||||
|
public class FuncDefinitionNode(string name, IEnumerable<FuncParameter> parameters, BlockNode body, Optional<Type> returnType) : DefinitionNode
|
||||||
{
|
{
|
||||||
public string Name { get; } = name;
|
public string Name { get; } = name;
|
||||||
public IEnumerable<FuncParameter> Parameters { get; } = parameters;
|
public IEnumerable<FuncParameter> Parameters { get; } = parameters;
|
||||||
public BlockNode Body { get; } = body;
|
public BlockNode Body { get; } = body;
|
||||||
|
public Optional<Type> ReturnType { get; } = returnType;
|
||||||
|
|
||||||
|
public override string ToString() => $"{Name}({Parameters.Select(p => p.ToString())}){(ReturnType.HasValue ? ": " + ReturnType.Value : "")}";
|
||||||
}
|
}
|
||||||
@@ -3,4 +3,9 @@
|
|||||||
public class IdentifierNode(string identifier) : ExpressionNode
|
public class IdentifierNode(string identifier) : ExpressionNode
|
||||||
{
|
{
|
||||||
public string Identifier { get; } = identifier;
|
public string Identifier { get; } = identifier;
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Identifier;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
namespace Nub.Lang.Parsing;
|
namespace Nub.Lang.Parsing;
|
||||||
|
|
||||||
public class LiteralNode(string value) : ExpressionNode
|
public class LiteralNode(string literal, Type type) : ExpressionNode
|
||||||
{
|
{
|
||||||
public string Value { get; } = value;
|
public string Literal { get; } = literal;
|
||||||
|
public Type LiteralType { get; } = type;
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,7 @@ public class Parser
|
|||||||
_tokens = tokens.ToArray();
|
_tokens = tokens.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<DefinitionNode> Parse()
|
public IReadOnlyCollection<DefinitionNode> Parse()
|
||||||
{
|
{
|
||||||
_index = 0;
|
_index = 0;
|
||||||
List<DefinitionNode> definitions = [];
|
List<DefinitionNode> definitions = [];
|
||||||
@@ -59,9 +59,15 @@ public class Parser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var returnType = Optional<Type>.Empty();
|
||||||
|
if (TryExpectSymbol(Symbol.Colon))
|
||||||
|
{
|
||||||
|
returnType = ParseType();
|
||||||
|
}
|
||||||
|
|
||||||
var body = ParseBlock();
|
var body = ParseBlock();
|
||||||
|
|
||||||
return new FuncDefinitionNode(name.Value, parameters, body);
|
return new FuncDefinitionNode(name.Value, parameters, body, returnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private FuncParameter ParseFuncParameter()
|
private FuncParameter ParseFuncParameter()
|
||||||
@@ -96,10 +102,10 @@ public class Parser
|
|||||||
|
|
||||||
if (identifier.Value == "syscall")
|
if (identifier.Value == "syscall")
|
||||||
{
|
{
|
||||||
return new SyscallNode(parameters);
|
return new SyscallStatementNode(new Syscall(parameters));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new FuncCallNode(identifier.Value, parameters);
|
return new FuncCallStatementNode(new FuncCall(identifier.Value, parameters));
|
||||||
}
|
}
|
||||||
case Symbol.Assign:
|
case Symbol.Assign:
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
@@ -117,12 +123,34 @@ public class Parser
|
|||||||
var token = ExpectToken();
|
var token = ExpectToken();
|
||||||
return token switch
|
return token switch
|
||||||
{
|
{
|
||||||
LiteralToken literal => new LiteralNode(literal.Value),
|
LiteralToken literal => new LiteralNode(literal.Value, literal.Type),
|
||||||
IdentifierToken identifier => new IdentifierNode(identifier.Value),
|
IdentifierToken identifier => ParseExpressionIdentifier(identifier),
|
||||||
_ => throw new Exception($"Unexpected token type {token.GetType().Name}")
|
_ => throw new Exception($"Unexpected token type {token.GetType().Name}")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ExpressionNode ParseExpressionIdentifier(IdentifierToken identifier)
|
||||||
|
{
|
||||||
|
if (TryExpectSymbol(Symbol.OpenParen))
|
||||||
|
{
|
||||||
|
List<ExpressionNode> parameters = [];
|
||||||
|
while (!TryExpectSymbol(Symbol.CloseParen))
|
||||||
|
{
|
||||||
|
parameters.Add(ParseExpression());
|
||||||
|
TryExpectSymbol(Symbol.Comma);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (identifier.Value == "syscall")
|
||||||
|
{
|
||||||
|
return new SyscallExpressionNode(new Syscall(parameters));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new FuncCallExpressionNode(new FuncCall(identifier.Value, parameters));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new IdentifierNode(identifier.Value);
|
||||||
|
}
|
||||||
|
|
||||||
private BlockNode ParseBlock()
|
private BlockNode ParseBlock()
|
||||||
{
|
{
|
||||||
ExpectSymbol(Symbol.OpenBrace);
|
ExpectSymbol(Symbol.OpenBrace);
|
||||||
@@ -137,8 +165,26 @@ public class Parser
|
|||||||
|
|
||||||
private Type ParseType()
|
private Type ParseType()
|
||||||
{
|
{
|
||||||
var name = ExpectIdentifier();
|
var name = ExpectIdentifier().Value;
|
||||||
return new Type(name.Value);
|
if (name == "Func")
|
||||||
|
{
|
||||||
|
List<Type> typeArguments = [];
|
||||||
|
if (TryExpectSymbol(Symbol.LessThan))
|
||||||
|
{
|
||||||
|
while (!TryExpectSymbol(Symbol.GreaterThan))
|
||||||
|
{
|
||||||
|
var type = ParseType();
|
||||||
|
typeArguments.Add(type);
|
||||||
|
TryExpectSymbol(Symbol.Comma);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var returnType = Optional<Type>.OfNullable(typeArguments.LastOrDefault());
|
||||||
|
|
||||||
|
return new DelegateType(typeArguments.Take(typeArguments.Count - 1), returnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return PrimitiveType.Parse(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Token ExpectToken()
|
private Token ExpectToken()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace Nub.Lang.Parsing;
|
namespace Nub.Lang.Parsing;
|
||||||
|
|
||||||
public class SyscallNode(IEnumerable<ExpressionNode> parameters) : StatementNode
|
public class Syscall(IEnumerable<ExpressionNode> parameters)
|
||||||
{
|
{
|
||||||
public IEnumerable<ExpressionNode> Parameters { get; } = parameters;
|
public IEnumerable<ExpressionNode> Parameters { get; } = parameters;
|
||||||
}
|
}
|
||||||
6
Nub.Lang/Nub.Lang/Parsing/SyscallExpressionNode.cs
Normal file
6
Nub.Lang/Nub.Lang/Parsing/SyscallExpressionNode.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Nub.Lang.Parsing;
|
||||||
|
|
||||||
|
public class SyscallExpressionNode(Syscall syscall) : ExpressionNode
|
||||||
|
{
|
||||||
|
public Syscall Syscall { get; } = syscall;
|
||||||
|
}
|
||||||
6
Nub.Lang/Nub.Lang/Parsing/SyscallStatementNode.cs
Normal file
6
Nub.Lang/Nub.Lang/Parsing/SyscallStatementNode.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Nub.Lang.Parsing;
|
||||||
|
|
||||||
|
public class SyscallStatementNode(Syscall syscall) : StatementNode
|
||||||
|
{
|
||||||
|
public Syscall Syscall { get; } = syscall;
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using Nub.Lang.Lexing;
|
using Nub.Lang.Lexing;
|
||||||
using Nub.Lang.Parsing;
|
using Nub.Lang.Parsing;
|
||||||
|
using Nub.Lang.Typing;
|
||||||
|
|
||||||
var src = File.ReadAllText(args[0]);
|
var src = File.ReadAllText(args[0]);
|
||||||
|
|
||||||
@@ -9,4 +10,5 @@ var tokens = lexer.Lex();
|
|||||||
var parser = new Parser(tokens);
|
var parser = new Parser(tokens);
|
||||||
var definitions = parser.Parse();
|
var definitions = parser.Parse();
|
||||||
|
|
||||||
Console.Read();
|
var typer = new ExpressionTyper(definitions);
|
||||||
|
typer.Populate();
|
||||||
@@ -1,26 +1,56 @@
|
|||||||
namespace Nub.Lang;
|
using Nub.Lib;
|
||||||
|
|
||||||
public class Type(string name)
|
namespace Nub.Lang;
|
||||||
|
|
||||||
|
public abstract class Type;
|
||||||
|
|
||||||
|
public class PrimitiveType(PrimitiveTypeKind kind) : Type
|
||||||
{
|
{
|
||||||
public static Type Bool => new("bool");
|
public static PrimitiveType Parse(string value)
|
||||||
public static Type Char => new("char");
|
{
|
||||||
|
var kind = value switch
|
||||||
|
{
|
||||||
|
"bool" => PrimitiveTypeKind.Bool,
|
||||||
|
"char" => PrimitiveTypeKind.Char,
|
||||||
|
"int8" => PrimitiveTypeKind.Int8,
|
||||||
|
"uint8" => PrimitiveTypeKind.UInt8,
|
||||||
|
"int16" => PrimitiveTypeKind.Int16,
|
||||||
|
"uint16" => PrimitiveTypeKind.UInt16,
|
||||||
|
"int32" => PrimitiveTypeKind.Int32,
|
||||||
|
"uint32" => PrimitiveTypeKind.UInt32,
|
||||||
|
"int64" => PrimitiveTypeKind.Int64,
|
||||||
|
"uint64" => PrimitiveTypeKind.UInt64,
|
||||||
|
"float" => PrimitiveTypeKind.Float,
|
||||||
|
"double" => PrimitiveTypeKind.Double,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(value), value, null)
|
||||||
|
};
|
||||||
|
|
||||||
|
return new PrimitiveType(kind);
|
||||||
|
}
|
||||||
|
|
||||||
public static Type Int8 => new("int8");
|
public PrimitiveTypeKind Kind { get; } = kind;
|
||||||
public static Type UInt8 => new("uint8");
|
}
|
||||||
|
|
||||||
public static Type Int16 => new("int16");
|
|
||||||
public static Type UInt16 => new("uint16");
|
|
||||||
|
|
||||||
public static Type Int32 => new("int32");
|
|
||||||
public static Type UInt32 => new("uint32");
|
|
||||||
|
|
||||||
public static Type Int64 => new("int64");
|
|
||||||
public static Type UInt64 => new("uint64");
|
|
||||||
|
|
||||||
public static Type Float => new("char");
|
|
||||||
public static Type Double => new("double");
|
|
||||||
|
|
||||||
public static Type Pointer => new("pointer");
|
|
||||||
|
|
||||||
public string Name = name;
|
public enum PrimitiveTypeKind
|
||||||
|
{
|
||||||
|
Bool,
|
||||||
|
Char,
|
||||||
|
Int8,
|
||||||
|
UInt8,
|
||||||
|
Int16,
|
||||||
|
UInt16,
|
||||||
|
Int32,
|
||||||
|
UInt32,
|
||||||
|
Int64,
|
||||||
|
UInt64,
|
||||||
|
Float,
|
||||||
|
Double,
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PointerType : Type;
|
||||||
|
|
||||||
|
public class DelegateType(IEnumerable<Type> parameters, Optional<Type> returnType) : Type
|
||||||
|
{
|
||||||
|
public IEnumerable<Type> Parameters { get; } = parameters;
|
||||||
|
public Optional<Type> ReturnType { get; } = returnType;
|
||||||
}
|
}
|
||||||
164
Nub.Lang/Nub.Lang/Typing/ExpressionTyper.cs
Normal file
164
Nub.Lang/Nub.Lang/Typing/ExpressionTyper.cs
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
using Nub.Lang.Parsing;
|
||||||
|
|
||||||
|
namespace Nub.Lang.Typing;
|
||||||
|
|
||||||
|
public class ExpressionTyper
|
||||||
|
{
|
||||||
|
private readonly IReadOnlyCollection<FuncDefinitionNode> _functions;
|
||||||
|
private readonly IReadOnlyCollection<GlobalVariableDefinitionNode> _variableDefinitions;
|
||||||
|
private readonly Stack<Variable> _variables;
|
||||||
|
|
||||||
|
public ExpressionTyper(IReadOnlyCollection<DefinitionNode> definitions)
|
||||||
|
{
|
||||||
|
_functions = definitions.OfType<FuncDefinitionNode>().ToList();
|
||||||
|
_variableDefinitions = definitions.OfType<GlobalVariableDefinitionNode>().ToList();
|
||||||
|
_variables = new Stack<Variable>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Populate()
|
||||||
|
{
|
||||||
|
_variables.Clear();
|
||||||
|
|
||||||
|
foreach (var variable in _variableDefinitions)
|
||||||
|
{
|
||||||
|
PopulateExpression(variable.Value);
|
||||||
|
_variables.Push(new Variable(variable.Name, variable.Value.Type));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var function in _functions)
|
||||||
|
{
|
||||||
|
foreach (var parameter in function.Parameters)
|
||||||
|
{
|
||||||
|
_variables.Push(new Variable(parameter.Name, parameter.Type));
|
||||||
|
}
|
||||||
|
PopulateBlock(function.Body);
|
||||||
|
for (var i = 0; i < function.Parameters.Count(); i++)
|
||||||
|
{
|
||||||
|
_variables.Pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PopulateBlock(BlockNode block)
|
||||||
|
{
|
||||||
|
var variableCount = _variables.Count;
|
||||||
|
foreach (var statement in block.Statements)
|
||||||
|
{
|
||||||
|
PopulateStatement(statement);
|
||||||
|
}
|
||||||
|
while (_variables.Count > variableCount)
|
||||||
|
{
|
||||||
|
_variables.Pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PopulateStatement(StatementNode statement)
|
||||||
|
{
|
||||||
|
switch (statement)
|
||||||
|
{
|
||||||
|
case FuncCallStatementNode funcCall:
|
||||||
|
PopulateFuncCallStatement(funcCall);
|
||||||
|
break;
|
||||||
|
case SyscallStatementNode syscall:
|
||||||
|
PopulateSyscallStatement(syscall);
|
||||||
|
break;
|
||||||
|
case VariableAssignmentNode variableAssignment:
|
||||||
|
PopulateVariableAssignment(variableAssignment);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(statement));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PopulateFuncCallStatement(FuncCallStatementNode funcCall)
|
||||||
|
{
|
||||||
|
foreach (var parameter in funcCall.FuncCall.Parameters)
|
||||||
|
{
|
||||||
|
PopulateExpression(parameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PopulateSyscallStatement(SyscallStatementNode syscall)
|
||||||
|
{
|
||||||
|
foreach (var parameter in syscall.Syscall.Parameters)
|
||||||
|
{
|
||||||
|
PopulateExpression(parameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PopulateVariableAssignment(VariableAssignmentNode variableAssignment)
|
||||||
|
{
|
||||||
|
PopulateExpression(variableAssignment.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PopulateExpression(ExpressionNode expression)
|
||||||
|
{
|
||||||
|
switch (expression)
|
||||||
|
{
|
||||||
|
case FuncCallExpressionNode funcCall:
|
||||||
|
PopulateFuncCallExpression(funcCall);
|
||||||
|
break;
|
||||||
|
case IdentifierNode identifier:
|
||||||
|
PopulateIdentifier(identifier);
|
||||||
|
break;
|
||||||
|
case LiteralNode literal:
|
||||||
|
PopulateLiteral(literal);
|
||||||
|
break;
|
||||||
|
case SyscallExpressionNode syscall:
|
||||||
|
PopulateSyscallExpression(syscall);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(expression));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PopulateFuncCallExpression(FuncCallExpressionNode funcCall)
|
||||||
|
{
|
||||||
|
foreach (var parameter in funcCall.FuncCall.Parameters)
|
||||||
|
{
|
||||||
|
PopulateExpression(parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
var function = _functions.FirstOrDefault(f => f.Name == funcCall.FuncCall.Name);
|
||||||
|
if (function == null)
|
||||||
|
{
|
||||||
|
throw new Exception($"Func {funcCall} is not defined");
|
||||||
|
}
|
||||||
|
if (!function.ReturnType.HasValue)
|
||||||
|
{
|
||||||
|
throw new Exception($"Func {funcCall} must have a return type when used in an expression");
|
||||||
|
}
|
||||||
|
funcCall.Type = function.ReturnType.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PopulateIdentifier(IdentifierNode identifier)
|
||||||
|
{
|
||||||
|
var type = _variables.FirstOrDefault(v => v.Name == identifier.Identifier)?.Type;
|
||||||
|
if (type == null)
|
||||||
|
{
|
||||||
|
throw new Exception($"Identifier {identifier} is not defined");
|
||||||
|
}
|
||||||
|
identifier.Type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void PopulateLiteral(LiteralNode literal)
|
||||||
|
{
|
||||||
|
literal.Type = literal.LiteralType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PopulateSyscallExpression(SyscallExpressionNode syscall)
|
||||||
|
{
|
||||||
|
foreach (var parameter in syscall.Syscall.Parameters)
|
||||||
|
{
|
||||||
|
PopulateExpression(parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall.Type = new PrimitiveType(PrimitiveTypeKind.Int64);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Variable(string name, Type type)
|
||||||
|
{
|
||||||
|
public string Name { get; } = name;
|
||||||
|
public Type Type { get; } = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user