...
This commit is contained in:
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user