...
This commit is contained in:
@@ -1,12 +1,29 @@
|
|||||||
namespace main
|
namespace main
|
||||||
|
|
||||||
export func main(args: []^string) {
|
struct Human {
|
||||||
c::printf("%d\n", args.count)
|
name: string
|
||||||
|
age: i64
|
||||||
let i: i64
|
}
|
||||||
|
|
||||||
while i < args.count {
|
export func main(args: []^string) {
|
||||||
c::printf("%s\n", args[i])
|
// c::printf("%d\n", args.count)
|
||||||
i = i + 1
|
|
||||||
|
// 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)
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -23,12 +23,12 @@ public interface IFuncSignature
|
|||||||
if (Name != name) return false;
|
if (Name != name) return false;
|
||||||
if (Parameters.Count == 0 && parameters.Count == 0) return true;
|
if (Parameters.Count == 0 && parameters.Count == 0) return true;
|
||||||
if (Parameters.Count > parameters.Count) return false;
|
if (Parameters.Count > parameters.Count) return false;
|
||||||
|
|
||||||
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))
|
||||||
{
|
{
|
||||||
@@ -45,7 +45,7 @@ public interface IFuncSignature
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user