This commit is contained in:
nub31
2025-06-02 15:52:06 +02:00
parent 96ad3d2677
commit 00a249f84d
4 changed files with 56 additions and 154 deletions

View File

@@ -1,12 +1,29 @@
namespace main namespace main
struct Human {
name: string
age: i64
}
export func main(args: []^string) { export func main(args: []^string) {
c::printf("%d\n", args.count) // c::printf("%d\n", args.count)
let i: i64 // let i: i64
while i < args.count { // while i < args.count {
c::printf("%s\n", args[i]) // c::printf("%s\n", args[i])
i = i + 1 // i = i + 1
// }
let human = alloc Human {
age = 23
name = "oliver"
} }
c::printf("%s is %d years old\n", human.name, human.age)
// human.name = "hubert"
// human.age = 92
c::printf("%s is %d years old\n", human.name, human.age)
} }

View File

@@ -1,4 +1,5 @@
using System.Globalization; using System.Diagnostics;
using System.Globalization;
using System.Text; using System.Text;
using Nub.Lang.Frontend.Parsing; using Nub.Lang.Frontend.Parsing;
using Nub.Lang.Frontend.Typing; using Nub.Lang.Frontend.Typing;
@@ -255,11 +256,6 @@ public class Generator
case NubStructType nubStructType: case NubStructType nubStructType:
{ {
var definition = LookupStructDefinition(nubStructType.Namespace, nubStructType.Name); var definition = LookupStructDefinition(nubStructType.Namespace, nubStructType.Name);
if (definition == null)
{
throw new Exception($"Cannot determine size of non-existent type {nubStructType}");
}
return definition.Fields.Sum(f => QbeTypeSize(f.Type)); return definition.Fields.Sum(f => QbeTypeSize(f.Type));
} }
case NubPointerType: case NubPointerType:
@@ -381,7 +377,7 @@ public class Generator
GenerateIf(ifStatement); GenerateIf(ifStatement);
break; break;
case MemberAssignmentNode memberAssignment: case MemberAssignmentNode memberAssignment:
throw new NotImplementedException(); GenerateMemberAssignment(memberAssignment);
break; break;
case ReturnNode @return: case ReturnNode @return:
GenerateReturn(@return); GenerateReturn(@return);
@@ -449,6 +445,17 @@ public class Generator
_builder.AppendLine($"@{endLabel}"); _builder.AppendLine($"@{endLabel}");
} }
private void GenerateMemberAssignment(MemberAssignmentNode memberAssignment)
{
var structType = memberAssignment.MemberAccess.Expression.Type as NubStructType;
Debug.Assert(structType != null);
var structDefinition = LookupStructDefinition(structType.Namespace, structType.Name);
var item = GenerateExpression(memberAssignment.MemberAccess.Expression);
var value = GenerateExpression(memberAssignment.Value);
}
private void GenerateReturn(ReturnNode @return) private void GenerateReturn(ReturnNode @return)
{ {
if (@return.Value.HasValue) if (@return.Value.HasValue)
@@ -1340,13 +1347,8 @@ public class Generator
private string GenerateStructInitializer(StructInitializerNode structInitializer) private string GenerateStructInitializer(StructInitializerNode structInitializer)
{ {
var structDefinition = LookupStructDefinition(structInitializer.StructType.Namespace, structInitializer.StructType.Name); var structDefinition = LookupStructDefinition(structInitializer.StructType.Namespace, structInitializer.StructType.Name);
if (structDefinition == null)
{
throw new Exception($"Struct {structInitializer.StructType.Name} is not defined");
}
var structVar = GenVarName(); var structVar = GenVarName();
var size = structDefinition.Fields.Sum(x => QbeTypeSize(x.Type)); var size = structDefinition.Fields.Sum(x => QbeTypeSize(x.Type));
_builder.AppendLine($" %{structVar} =l alloc8 {size}"); _builder.AppendLine($" %{structVar} =l alloc8 {size}");
@@ -1426,7 +1428,7 @@ public class Generator
private string GenerateMemberAccess(MemberAccessNode memberAccess) private string GenerateMemberAccess(MemberAccessNode memberAccess)
{ {
var expression = GenerateExpression(memberAccess.Expression); var item = GenerateExpression(memberAccess.Expression);
switch (memberAccess.Expression.Type) switch (memberAccess.Expression.Type)
{ {
@@ -1435,7 +1437,7 @@ public class Generator
if (memberAccess.Member == "count") if (memberAccess.Member == "count")
{ {
var outputName = GenVarName(); var outputName = GenVarName();
_builder.AppendLine($" %{outputName} =l loadl {expression}"); _builder.AppendLine($" %{outputName} =l loadl {item}");
return $"%{outputName}"; return $"%{outputName}";
} }
@@ -1443,29 +1445,10 @@ public class Generator
} }
case NubStructType structType: case NubStructType structType:
{ {
var structDefinition = LookupStructDefinition(structType.Namespace, structType.Namespace); var structDefinition = LookupStructDefinition(structType.Namespace, structType.Name);
if (structDefinition == null)
{
throw new Exception($"Struct {structType.Name} is not defined");
}
var fieldIndex = -1;
for (var i = 0; i < structDefinition.Fields.Count; i++)
{
if (structDefinition.Fields[i].Name == memberAccess.Member)
{
fieldIndex = i;
break;
}
}
if (fieldIndex == -1)
{
throw new Exception($"Field {memberAccess.Member} is not defined in struct {structType.Name}");
}
var offsetName = GenVarName(); var offsetName = GenVarName();
_builder.AppendLine($" %{offsetName} =l add {expression}, {fieldIndex * QbeTypeSize(memberAccess.Type)}"); _builder.AppendLine($" %{offsetName} =l add {item}, {LookupStructOffset(structDefinition, memberAccess.Member)}");
var outputName = GenVarName(); var outputName = GenVarName();
_builder.AppendLine($" %{outputName} ={SQT(memberAccess.Type)} load{SQT(memberAccess.Type)} %{offsetName}"); _builder.AppendLine($" %{outputName} ={SQT(memberAccess.Type)} load{SQT(memberAccess.Type)} %{offsetName}");
@@ -1540,22 +1523,27 @@ public class Generator
return $"l{++_labelIndex}"; return $"l{++_labelIndex}";
} }
private IFuncSignature? LookupFuncSignature(string @namespace, string name, List<NubType> parameters) private IFuncSignature LookupFuncSignature(string @namespace, string name, List<NubType> parameters)
{ {
return _sourceFiles return _sourceFiles
.Where(f => f.Namespace == @namespace) .Where(f => f.Namespace == @namespace)
.SelectMany(f => f.Definitions) .SelectMany(f => f.Definitions)
.OfType<IFuncSignature>() .OfType<IFuncSignature>()
.FirstOrDefault(f => f.SignatureMatches(name, parameters)); .Single(f => f.SignatureMatches(name, parameters));
} }
private StructDefinitionNode? LookupStructDefinition(string @namespace, string name) private StructDefinitionNode LookupStructDefinition(string @namespace, string name)
{ {
return _sourceFiles return _sourceFiles
.Where(f => f.Namespace == @namespace) .Where(f => f.Namespace == @namespace)
.SelectMany(f => f.Definitions) .SelectMany(f => f.Definitions)
.OfType<StructDefinitionNode>() .OfType<StructDefinitionNode>()
.FirstOrDefault(d => d.Name == name); .Single(s => s.Name == name);
}
private int LookupStructOffset(StructDefinitionNode structDefinition, string member)
{
return structDefinition.Fields.TakeWhile(f => f.Name != member).Sum(f => QbeTypeSize(f.Type));
} }
private class Variable private class Variable

View File

@@ -26,9 +26,9 @@ public interface IFuncSignature
for (var i = 0; i < parameters.Count; i++) for (var i = 0; i < parameters.Count; i++)
{ {
if (i > Parameters.Count) if (i >= Parameters.Count)
{ {
if (Parameters[^1].Variadic) if (Parameters.Count > 0 && Parameters[^1].Variadic)
{ {
if (!NubType.IsCompatibleWith(parameters[i], Parameters[^1].Type)) if (!NubType.IsCompatibleWith(parameters[i], Parameters[^1].Type))
{ {

View File

@@ -249,109 +249,6 @@ public class Parser
return new StatementExpressionNode(GetTokensForNode(startIndex), expr); return new StatementExpressionNode(GetTokensForNode(startIndex), expr);
} }
// private StatementNode ParseStatementIdentifier(int startIndex)
// {
// var leftExpr = ParsePrimaryExpression();
//
// var symbol = ExpectSymbol();
//
// switch (symbol.Symbol)
// {
// case Symbol.DoubleColon:
// {
// if (leftExpr is not IdentifierNode namespaceNode)
// {
// throw new ParseException(Diagnostic
// .Error("Invalid syntax before '::'")
// .WithHelp("Only identifiers can be used before '::' for namespace resolution")
// .At(symbol)
// .Build());
// }
//
// var name = ExpectIdentifier();
// ExpectSymbol(Symbol.OpenParen);
// var parameters = new List<ExpressionNode>();
// while (!TryExpectSymbol(Symbol.CloseParen))
// {
// parameters.Add(ParseExpression());
// if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var nextToken) && nextToken is not SymbolToken { Symbol: Symbol.CloseParen })
// {
// _diagnostics.Add(Diagnostic
// .Warning("Missing comma between function arguments")
// .WithHelp("Add a ',' to separate arguments")
// .At(nextToken)
// .Build());
// }
// }
//
// return new FuncCallStatementNode(GetTokensForNode(startIndex), new FuncCall(namespaceNode.Identifier, name.Value, parameters));
// }
// case Symbol.OpenParen:
// {
// if (leftExpr is not IdentifierNode funcNode)
// {
// throw new ParseException(Diagnostic
// .Error("Invalid syntax before '('")
// .WithHelp("Only identifiers can be called as functions")
// .At(symbol)
// .Build());
// }
//
// var parameters = new List<ExpressionNode>();
// while (!TryExpectSymbol(Symbol.CloseParen))
// {
// parameters.Add(ParseExpression());
// if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var nextToken) && nextToken is not SymbolToken { Symbol: Symbol.CloseParen })
// {
// _diagnostics.Add(Diagnostic
// .Warning("Missing comma between function arguments")
// .WithHelp("Add a ',' to separate arguments")
// .At(nextToken)
// .Build());
// }
// }
//
// return new FuncCallStatementNode(GetTokensForNode(startIndex), new FuncCall(_namespace, funcNode.Identifier, parameters));
// }
// case Symbol.Assign:
// {
// var value = ParseExpression();
//
// switch (leftExpr)
// {
// case IdentifierNode identifierNode:
// {
// return new VariableAssignmentNode(GetTokensForNode(startIndex), identifierNode.Identifier, value);
// }
// case ArrayIndexNode arrayIndexNode:
// {
// return new ArrayIndexAssignmentNode(GetTokensForNode(startIndex), arrayIndexNode.Expression, arrayIndexNode.Index, value);
// }
// case MemberAccessNode memberAccessNode:
// {
// return new MemberAssignmentNode(GetTokensForNode(startIndex), memberAccessNode.Expression, memberAccessNode.Member, value);
// }
// default:
// {
// throw new ParseException(Diagnostic
// .Error("Invalid left-hand side in assignment")
// .WithHelp("Left side must be a variable, array element, or struct member")
// .At(symbol)
// .Build());
// }
// }
// }
// default:
// {
// throw new ParseException(Diagnostic
// .Error($"Unexpected symbol '{symbol.Symbol}' after identifier")
// .WithHelp("Expected '(', '=', or '::' after identifier")
// .At(symbol)
// .Build());
// }
// }
// }
private VariableDeclarationNode ParseVariableDeclaration(int startIndex) private VariableDeclarationNode ParseVariableDeclaration(int startIndex)
{ {
ExpectSymbol(Symbol.Let); ExpectSymbol(Symbol.Let);