Add support for expression syscalls
This commit is contained in:
@@ -146,23 +146,36 @@ public class Generator
|
||||
GenerateFuncCall(funcCallStatement.FuncCall, func);
|
||||
break;
|
||||
case ReturnNode @return:
|
||||
if (@return.Value.HasValue)
|
||||
{
|
||||
GenerateExpression(@return.Value.Value, func);
|
||||
}
|
||||
_builder.AppendLine($" jmp {func.EndLabel}");
|
||||
GenerateReturn(func, @return);
|
||||
break;
|
||||
case SyscallStatementNode syscallStatement:
|
||||
GenerateSyscall(syscallStatement.Syscall, func);
|
||||
break;
|
||||
case VariableAssignmentNode variableAssignment:
|
||||
throw new NotImplementedException();
|
||||
GenerateVariableAssignment(func, variableAssignment);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(statement));
|
||||
}
|
||||
}
|
||||
|
||||
private void GenerateReturn(Func func, ReturnNode @return)
|
||||
{
|
||||
if (@return.Value.HasValue)
|
||||
{
|
||||
GenerateExpression(@return.Value.Value, func);
|
||||
}
|
||||
|
||||
_builder.AppendLine($" jmp {func.EndLabel}");
|
||||
}
|
||||
|
||||
private void GenerateVariableAssignment(Func func, VariableAssignmentNode variableAssignment)
|
||||
{
|
||||
GenerateExpression(variableAssignment.Value, func);
|
||||
var variable = func.ResolveLocalVariable(variableAssignment.Name);
|
||||
_builder.AppendLine($" mov [rbp - {variable.Offset}], rax");
|
||||
}
|
||||
|
||||
private void GenerateExpression(ExpressionNode expression, Func func)
|
||||
{
|
||||
switch (expression)
|
||||
@@ -180,7 +193,7 @@ public class Generator
|
||||
GenerateStrlen(strlen, func);
|
||||
break;
|
||||
case SyscallExpressionNode syscallExpression:
|
||||
throw new NotImplementedException();
|
||||
GenerateSyscall(syscallExpression.Syscall, func);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(expression));
|
||||
|
||||
@@ -4,13 +4,9 @@ let STD_OUT = 1;
|
||||
let STD_ERR = 2;
|
||||
|
||||
func main() {
|
||||
write(test());
|
||||
write("test\n");
|
||||
}
|
||||
|
||||
func test(): String {
|
||||
return "test";
|
||||
}
|
||||
|
||||
func write(msg: String) {
|
||||
syscall(SYS_WRITE, STD_OUT, msg, strlen(msg));
|
||||
func write(msg: String): int64 {
|
||||
return syscall(SYS_WRITE, STD_OUT, msg, strlen(msg));
|
||||
}
|
||||
@@ -129,6 +129,14 @@ public class Parser
|
||||
|
||||
return new ReturnNode(value);
|
||||
}
|
||||
case Symbol.Let:
|
||||
{
|
||||
var name = ExpectIdentifier().Value;
|
||||
ExpectSymbol(Symbol.Assign);
|
||||
var value = ParseExpression();
|
||||
ExpectSymbol(Symbol.Semicolon);
|
||||
return new VariableAssignmentNode(name, value);
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new Exception($"Unexpected symbol {symbol.Symbol}");
|
||||
|
||||
@@ -100,6 +100,7 @@ public class ExpressionTyper
|
||||
private void PopulateVariableAssignment(VariableAssignmentNode variableAssignment)
|
||||
{
|
||||
PopulateExpression(variableAssignment.Value);
|
||||
_variables.Push(new Variable(variableAssignment.Name, variableAssignment.Value.Type));
|
||||
}
|
||||
|
||||
private void PopulateExpression(ExpressionNode expression)
|
||||
@@ -150,7 +151,7 @@ public class ExpressionTyper
|
||||
var type = _variables.FirstOrDefault(v => v.Name == identifier.Identifier)?.Type;
|
||||
if (type == null)
|
||||
{
|
||||
throw new Exception($"Identifier {identifier} is not defined");
|
||||
throw new Exception($"Variable {identifier} is not defined");
|
||||
}
|
||||
identifier.Type = type;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user