This commit is contained in:
nub31
2025-05-08 18:57:38 +02:00
parent 1429c3a993
commit 626b2fef0c
5 changed files with 124 additions and 64 deletions

View File

@@ -1,12 +1,20 @@
import "c"; import "c";
struct Human { struct Human {
age: int64; age: int64 = 0;
name: string; name: string;
} }
global func main() { global func main() {
printName(); while true {
let dad = new Human
{
name = "John";
};
printName(dad);
}
} }
func printName(human: Human) { func printName(human: Human) {

View File

@@ -44,17 +44,22 @@ public class Generator
private string QbeTypeName(NubType type) private string QbeTypeName(NubType type)
{ {
if (type.Equals(NubType.Int64) || type.Equals(NubType.String))
{
return "l";
}
if (type.Equals(NubType.Int32) || type.Equals(NubType.Bool)) if (type.Equals(NubType.Int32) || type.Equals(NubType.Bool))
{ {
return "w"; return "w";
} }
return $":{type.Name}"; return "l";
}
private int QbeTypeSize(NubType type)
{
if (type.Equals(NubType.Int32) || type.Equals(NubType.Bool))
{
return 4;
}
return 8;
} }
private void GenerateFuncDefinition(LocalFuncDefinitionNode node) private void GenerateFuncDefinition(LocalFuncDefinitionNode node)
@@ -261,25 +266,49 @@ public class Generator
return GenerateLiteral(literal); return GenerateLiteral(literal);
case StructInitializerNode structInitializer: case StructInitializerNode structInitializer:
return GenerateStructInitializer(structInitializer); return GenerateStructInitializer(structInitializer);
case StructMemberAccessorNode structMemberAccessor: case StructFieldAccessorNode structMemberAccessor:
return GenerateStructMemberAccessor(structMemberAccessor); return GenerateStructFieldAccessor(structMemberAccessor);
default: default:
throw new ArgumentOutOfRangeException(nameof(expression)); throw new ArgumentOutOfRangeException(nameof(expression));
} }
} }
private string GenerateStructMemberAccessor(StructMemberAccessorNode structMemberAccessor) private string GenerateStructFieldAccessor(StructFieldAccessorNode structFieldAccessor)
{ {
var type = _variables.First(x => x.Key == structMemberAccessor.Fields[0]).Value.Type; var structType = structFieldAccessor.Struct.Type;
var def = _definitions.OfType<StructDefinitionNode>().FirstOrDefault(s => s.Name == type.Name); var structDefinition = _definitions
if (def == null) .OfType<StructDefinitionNode>()
.FirstOrDefault(s => s.Name == structType.Name);
if (structDefinition == null)
{ {
throw new Exception("def is null"); throw new Exception($"Struct {structType.Name} is not defined");
} }
throw new NotImplementedException("Not finished yet"); var @struct = GenerateExpression(structFieldAccessor.Struct);
return $"load{QbeTypeName(structMemberAccessor.Type)} "; var fieldIndex = -1;
for (var i = 0; i < structDefinition.Fields.Count; i++)
{
if (structDefinition.Fields[i].Name == structFieldAccessor.Field)
{
fieldIndex = i;
break;
}
}
if (fieldIndex == -1)
{
throw new Exception($"Field {structFieldAccessor.Field} is not defined in struct {structType.Name}");
}
var offsetLabel = GenName("offset");
_builder.AppendLine($" %{offsetLabel} ={QbeTypeName(structFieldAccessor.Type)} add {@struct}, {fieldIndex * QbeTypeSize(structFieldAccessor.Type)}");
var outputLabel = GenName("field");
_builder.AppendLine($" %{outputLabel} ={QbeTypeName(structFieldAccessor.Type)} load{QbeTypeName(structFieldAccessor.Type)} %{offsetLabel}");
return $"%{outputLabel}";
} }
private string GenerateBinaryExpression(BinaryExpressionNode binaryExpression) private string GenerateBinaryExpression(BinaryExpressionNode binaryExpression)
@@ -317,7 +346,44 @@ public class Generator
private string GenerateStructInitializer(StructInitializerNode structInitializer) private string GenerateStructInitializer(StructInitializerNode structInitializer)
{ {
throw new NotImplementedException(); var structDefinition = _definitions.OfType<StructDefinitionNode>()
.FirstOrDefault(s => s.Name == structInitializer.StructType.Name);
if (structDefinition == null)
{
throw new Exception($"Struct {structInitializer.StructType.Name} is not defined");
}
var structVar = GenName("struct");
var size = structDefinition.Fields.Sum(x => QbeTypeSize(x.Type));
_builder.AppendLine($" %{structVar} =l alloc8 {size}");
for (var i = 0; i < structDefinition.Fields.Count; i++)
{
var field = structDefinition.Fields[i];
if (structInitializer.Initializers.TryGetValue(field.Name, out var fieldValue))
{
var var = GenerateExpression(fieldValue);
var offsetLabel = GenName("offset");
_builder.AppendLine($" %{offsetLabel} =l add %{structVar}, {i * QbeTypeSize(field.Type)}");
_builder.AppendLine($" store{QbeTypeName(field.Type)} {var}, %{offsetLabel}");
}
else if (field.Value.HasValue)
{
var var = GenerateExpression(field.Value.Value);
var offsetLabel = GenName("offset");
_builder.AppendLine($" %{offsetLabel} =l add %{structVar}, {i * QbeTypeSize(field.Type)}");
_builder.AppendLine($" store{QbeTypeName(field.Type)} {var}, %{offsetLabel}");
}
else
{
throw new Exception($"Field {field.Name} on struct {structInitializer.StructType.Name} is not initialized");
}
}
return $"%{structVar}";
} }
private string GenerateExpressionFuncCall(FuncCallExpressionNode funcCall) private string GenerateExpressionFuncCall(FuncCallExpressionNode funcCall)

View File

@@ -396,7 +396,9 @@ public class Parser
return new StructInitializerNode(type, initializers); return new StructInitializerNode(type, initializers);
} }
default: default:
{
throw new Exception($"Unknown symbol: {symbolToken.Symbol}"); throw new Exception($"Unknown symbol: {symbolToken.Symbol}");
}
} }
} }
default: default:
@@ -421,18 +423,15 @@ public class Parser
case Symbol.Period: case Symbol.Period:
{ {
Next(); Next();
List<string> members = ExpressionNode result = new IdentifierNode(identifier.Value);
[
identifier.Value,
ExpectIdentifier().Value
];
while (TryExpectSymbol(Symbol.Period)) do
{ {
members.Add(ExpectIdentifier().Value); var field = ExpectIdentifier();
} result = new StructFieldAccessorNode(result, field.Value);
} while (TryExpectSymbol(Symbol.Period));
return new StructMemberAccessorNode(members); return result;
} }
case Symbol.OpenParen: case Symbol.OpenParen:
{ {

View File

@@ -1,6 +1,7 @@
namespace Nub.Lang.Frontend.Parsing; namespace Nub.Lang.Frontend.Parsing;
public class StructFieldAccessorNode(List<string> fields) : ExpressionNode public class StructFieldAccessorNode(ExpressionNode @struct, string field) : ExpressionNode
{ {
public List<string> Fields { get; } = fields; public ExpressionNode Struct { get; } = @struct;
public string Field { get; } = field;
} }

View File

@@ -179,8 +179,8 @@ public class ExpressionTyper
case StructInitializerNode structInitializer: case StructInitializerNode structInitializer:
PopulateStructInitializer(structInitializer); PopulateStructInitializer(structInitializer);
break; break;
case StructMemberAccessorNode structMemberAccessor: case StructFieldAccessorNode structMemberAccessor:
GenerateStructMemberAccessorNode(structMemberAccessor); PopulateStructMemberAccessorNode(structMemberAccessor);
break; break;
default: default:
throw new ArgumentOutOfRangeException(nameof(expression)); throw new ArgumentOutOfRangeException(nameof(expression));
@@ -262,43 +262,29 @@ public class ExpressionTyper
structInitializer.Type = structInitializer.StructType; structInitializer.Type = structInitializer.StructType;
} }
// TODO: Fix this ugly ass code private void PopulateStructMemberAccessorNode(StructFieldAccessorNode structFieldAccessor)
private void GenerateStructMemberAccessorNode(StructMemberAccessorNode structMemberAccessor)
{ {
var variable = _variables.FirstOrDefault(v => v.Name == structMemberAccessor.Fields[0]); PopulateExpression(structFieldAccessor.Struct);
if (variable == null)
var structType = structFieldAccessor.Struct.Type;
if (structType == null)
{ {
throw new Exception($"Variable {structMemberAccessor.Fields[0]} is not defined"); throw new Exception($"Cannot access field on non-struct type: {structFieldAccessor.Struct}");
} }
var definition = _structDefinitions.FirstOrDefault(sd => sd.Name == variable.Type.Name); var structDefinition = _structDefinitions.FirstOrDefault(s => s.Name == structType.Name);
if (definition == null) if (structDefinition == null)
{ {
throw new Exception($"Struct {structMemberAccessor.Fields[0]} is not defined"); throw new Exception($"Struct {structType.Name} is not defined");
} }
for (var i = 1; i < structMemberAccessor.Fields.Count - 1; i++) var field = structDefinition.Fields.FirstOrDefault(f => f.Name == structFieldAccessor.Field);
if (field == null)
{ {
var member = definition.Fields.FirstOrDefault(m => m.Name == structMemberAccessor.Fields[i]); throw new Exception($"Field {structFieldAccessor.Field} is not defined in struct {structType.Name}");
if (member == null)
{
throw new Exception($"Member {structMemberAccessor.Fields[i]} does not exist on struct {definition.Name}");
}
definition = _structDefinitions.FirstOrDefault(sd => sd.Name == member.Type.Name);
if (definition == null)
{
throw new Exception($"Struct {structMemberAccessor.Fields[i]} is not defined");
}
} }
var tmp = definition.Fields.FirstOrDefault(m => m.Name == structMemberAccessor.Fields.Last()); structFieldAccessor.Type = field.Type;
if (tmp == null)
{
throw new Exception($"Member {structMemberAccessor.Fields.Last()} does not exist on struct {definition.Name}");
}
structMemberAccessor.Type = tmp.Type;
} }
private class Variable(string name, NubType type) private class Variable(string name, NubType type)