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