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
export func main(args: []^string) {
c::printf("%d\n", args.count)
let i: i64
struct Human {
name: string
age: i64
}
while i < args.count {
c::printf("%s\n", args[i])
i = i + 1
export func main(args: []^string) {
// c::printf("%d\n", args.count)
// let i: i64
// while i < args.count {
// c::printf("%s\n", args[i])
// 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 Nub.Lang.Frontend.Parsing;
using Nub.Lang.Frontend.Typing;
@@ -255,11 +256,6 @@ public class Generator
case NubStructType nubStructType:
{
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));
}
case NubPointerType:
@@ -381,7 +377,7 @@ public class Generator
GenerateIf(ifStatement);
break;
case MemberAssignmentNode memberAssignment:
throw new NotImplementedException();
GenerateMemberAssignment(memberAssignment);
break;
case ReturnNode @return:
GenerateReturn(@return);
@@ -449,6 +445,17 @@ public class Generator
_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)
{
if (@return.Value.HasValue)
@@ -1340,13 +1347,8 @@ public class Generator
private string GenerateStructInitializer(StructInitializerNode structInitializer)
{
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 size = structDefinition.Fields.Sum(x => QbeTypeSize(x.Type));
_builder.AppendLine($" %{structVar} =l alloc8 {size}");
@@ -1426,7 +1428,7 @@ public class Generator
private string GenerateMemberAccess(MemberAccessNode memberAccess)
{
var expression = GenerateExpression(memberAccess.Expression);
var item = GenerateExpression(memberAccess.Expression);
switch (memberAccess.Expression.Type)
{
@@ -1435,7 +1437,7 @@ public class Generator
if (memberAccess.Member == "count")
{
var outputName = GenVarName();
_builder.AppendLine($" %{outputName} =l loadl {expression}");
_builder.AppendLine($" %{outputName} =l loadl {item}");
return $"%{outputName}";
}
@@ -1443,29 +1445,10 @@ public class Generator
}
case NubStructType structType:
{
var structDefinition = LookupStructDefinition(structType.Namespace, structType.Namespace);
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 structDefinition = LookupStructDefinition(structType.Namespace, structType.Name);
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();
_builder.AppendLine($" %{outputName} ={SQT(memberAccess.Type)} load{SQT(memberAccess.Type)} %{offsetName}");
@@ -1540,22 +1523,27 @@ public class Generator
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
.Where(f => f.Namespace == @namespace)
.SelectMany(f => f.Definitions)
.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
.Where(f => f.Namespace == @namespace)
.SelectMany(f => f.Definitions)
.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

View File

@@ -23,12 +23,12 @@ public interface IFuncSignature
if (Name != name) return false;
if (Parameters.Count == 0 && parameters.Count == 0) return true;
if (Parameters.Count > parameters.Count) return false;
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))
{
@@ -45,7 +45,7 @@ public interface IFuncSignature
return false;
}
}
return true;
}

View File

@@ -249,109 +249,6 @@ public class Parser
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)
{
ExpectSymbol(Symbol.Let);