...
This commit is contained in:
@@ -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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
throw new Exception("def is null");
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new NotImplementedException("Not finished yet");
|
if (structDefinition == null)
|
||||||
|
{
|
||||||
|
throw new Exception($"Struct {structType.Name} is not defined");
|
||||||
|
}
|
||||||
|
|
||||||
|
var @struct = GenerateExpression(structFieldAccessor.Struct);
|
||||||
|
|
||||||
|
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)}");
|
||||||
|
|
||||||
return $"load{QbeTypeName(structMemberAccessor.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)
|
||||||
|
|||||||
@@ -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,
|
do
|
||||||
ExpectIdentifier().Value
|
|
||||||
];
|
|
||||||
|
|
||||||
while (TryExpectSymbol(Symbol.Period))
|
|
||||||
{
|
{
|
||||||
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:
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user