diff --git a/example/math/math.nub b/example/math/math.nub new file mode 100644 index 0000000..267b678 --- /dev/null +++ b/example/math/math.nub @@ -0,0 +1,5 @@ +namespace math + +func add(a: i64, b: i64): i64 { + return a + b +} \ No newline at end of file diff --git a/example/program.nub b/example/program.nub index 2a46b39..fd7875b 100644 --- a/example/program.nub +++ b/example/program.nub @@ -2,9 +2,11 @@ namespace main /// # Documentation /// ## Documentation subtitle -global func main(args: []string) { +export func main(args: []string) { i = 0 + x = math::add(1, 1) + c::printf("%d\n", args.count) while i < args.count { diff --git a/src/compiler/Nub.Lang/Backend/Generator.cs b/src/compiler/Nub.Lang/Backend/Generator.cs index 7351a95..0f48816 100644 --- a/src/compiler/Nub.Lang/Backend/Generator.cs +++ b/src/compiler/Nub.Lang/Backend/Generator.cs @@ -14,7 +14,10 @@ public class Generator private Stack _breakLabels = []; private Stack _continueLabels = []; private int _variableIndex; + private int _labelIndex; + private int _funcIndex; private bool _codeIsReachable = true; + private Dictionary _funcNames = []; public string Generate(List sourceFiles) { @@ -22,9 +25,12 @@ public class Generator _builder = new StringBuilder(); _variables = new Dictionary(); _strings = []; + _funcNames = []; _breakLabels = []; _continueLabels = []; _variableIndex = 0; + _funcIndex = 0; + _labelIndex = 0; _codeIsReachable = true; foreach (var structDef in _sourceFiles.SelectMany(f => f.Definitions).OfType()) @@ -32,6 +38,29 @@ public class Generator GenerateStructDefinition(structDef); _builder.AppendLine(); } + + foreach (var funcSignature in _sourceFiles.SelectMany(f => f.Definitions).OfType()) + { + switch (funcSignature) + { + case ExternFuncDefinitionNode externFuncDefinitionNode: + _funcNames[funcSignature] = externFuncDefinitionNode.Name; + break; + case LocalFuncDefinitionNode localFuncDefinitionNode: + if (localFuncDefinitionNode.Exported) + { + _funcNames[funcSignature] = localFuncDefinitionNode.Name; + } + else + { + var funcName = GenFuncName(); + _funcNames[funcSignature] = funcName; + } + break; + default: + throw new ArgumentOutOfRangeException(nameof(funcSignature)); + } + } foreach (var funcDef in _sourceFiles.SelectMany(f => f.Definitions).OfType()) { @@ -244,7 +273,7 @@ public class Generator { _variables.Clear(); - if (node.Global) + if (node.Exported) { _builder.Append("export "); } @@ -260,7 +289,7 @@ public class Generator } _builder.Append('$'); - _builder.Append(node.Name); + _builder.Append(_funcNames[node]); var parameterStrings = node.Parameters.Select(parameter => parameter.Variadic ? "..." : $"{FQT(parameter.Type)} %{parameter.Name}"); @@ -276,31 +305,31 @@ public class Generator switch (FQT(parameter.Type)) { case "sb": - parameterName = GenName(); + parameterName = GenVarName(); _builder.AppendLine($" %{parameterName} =w extsb %{parameter.Name}"); break; case "ub": - parameterName = GenName(); + parameterName = GenVarName(); _builder.AppendLine($" %{parameterName} =w extub %{parameter.Name}"); break; case "sh": - parameterName = GenName(); + parameterName = GenVarName(); _builder.AppendLine($" %{parameterName} =w extsh %{parameter.Name}"); break; case "uh": - parameterName = GenName(); + parameterName = GenVarName(); _builder.AppendLine($" %{parameterName} =w extuh %{parameter.Name}"); break; } - var pointerLabel = GenName(); - _builder.AppendLine($" %{pointerLabel} ={SQT(parameter.Type)} alloc8 {QbeTypeSize(parameter.Type)}"); - _builder.AppendLine($" storel %{parameterName}, %{pointerLabel}"); + var pointerName = GenVarName(); + _builder.AppendLine($" %{pointerName} ={SQT(parameter.Type)} alloc8 {QbeTypeSize(parameter.Type)}"); + _builder.AppendLine($" storel %{parameterName}, %{pointerName}"); _variables[parameter.Name] = new Variable { - Pointer = $"%{pointerLabel}", + Pointer = $"%{pointerName}", Type = parameter.Type }; } @@ -403,7 +432,9 @@ public class Generator parameterStrings.Add($"{qbeParameterType} {result}"); } - return $"call ${funcCall.Name}({string.Join(", ", parameterStrings)})"; + var funcName = _funcNames[funcDefinition]; + + return $"call ${funcName}({string.Join(", ", parameterStrings)})"; } private void GenerateBlock(BlockNode block) @@ -436,9 +467,9 @@ public class Generator private void GenerateIf(IfNode ifStatement) { - var trueLabel = GenName(); - var falseLabel = GenName(); - var endLabel = GenName(); + var trueLabel = GenLabelName(); + var falseLabel = GenLabelName(); + var endLabel = GenLabelName(); var result = GenerateExpression(ifStatement.Condition); _builder.AppendLine($" jnz {result}, @{trueLabel}, @{falseLabel}"); @@ -481,13 +512,13 @@ public class Generator } else { - var pointerLabel = GenName(); - _builder.AppendLine($" %{pointerLabel} ={SQT(variableAssignment.Value.Type)} alloc8 {QbeTypeSize(variableAssignment.Value.Type)}"); - _builder.AppendLine($" storel {result}, %{pointerLabel}"); + var pointerName = GenVarName(); + _builder.AppendLine($" %{pointerName} ={SQT(variableAssignment.Value.Type)} alloc8 {QbeTypeSize(variableAssignment.Value.Type)}"); + _builder.AppendLine($" storel {result}, %{pointerName}"); _variables[variableAssignment.Name] = new Variable { - Pointer = $"%{pointerLabel}", + Pointer = $"%{pointerName}", Type = variableAssignment.Value.Type }; } @@ -495,9 +526,9 @@ public class Generator private void GenerateWhile(WhileNode whileStatement) { - var conditionLabel = GenName(); - var iterationLabel = GenName(); - var endLabel = GenName(); + var conditionLabel = GenLabelName(); + var iterationLabel = GenLabelName(); + var endLabel = GenLabelName(); _breakLabels.Push(endLabel); _continueLabels.Push(conditionLabel); @@ -540,29 +571,29 @@ public class Generator var arrayBaseType = ((NubArrayType)arrayIndex.Expression.Type).BaseType; - var firstItem = GenName(); - _builder.AppendLine($" %{firstItem} =l add {array}, 8"); - var adjustedIndex = GenName(); - _builder.AppendLine($" %{adjustedIndex} =l mul {index}, {QbeTypeSize(arrayBaseType)}"); - var indexLabel = GenName(); - _builder.AppendLine($" %{indexLabel} ={SQT(arrayIndex.Type)} add %{firstItem}, %{adjustedIndex}"); - var outputLabel = GenName(); - _builder.AppendLine($" %{outputLabel} =l load{SQT(arrayBaseType)} %{indexLabel}"); - return $"%{outputLabel}"; + var firstItemPointerName = GenVarName(); + _builder.AppendLine($" %{firstItemPointerName} =l add {array}, 8"); + var offsetPointerName = GenVarName(); + _builder.AppendLine($" %{offsetPointerName} =l mul {index}, {QbeTypeSize(arrayBaseType)}"); + var resultPointerName = GenVarName(); + _builder.AppendLine($" %{resultPointerName} ={SQT(arrayIndex.Type)} add %{firstItemPointerName}, %{offsetPointerName}"); + var outputName = GenVarName(); + _builder.AppendLine($" %{outputName} =l load{SQT(arrayBaseType)} %{resultPointerName}"); + return $"%{outputName}"; } private string GenerateDereference(DereferenceNode dereference) { var result = GenerateExpression(dereference.Expression); - var outputLabel = GenName(); - _builder.AppendLine($" %{outputLabel} ={SQT(dereference.Type)} load{SQT(dereference.Type)} {result}"); - return $"%{outputLabel}"; + var outputName = GenVarName(); + _builder.AppendLine($" %{outputName} ={SQT(dereference.Type)} load{SQT(dereference.Type)} {result}"); + return $"%{outputName}"; } private string GenerateAddressOf(AddressOfNode addressOf) { var result = GenerateExpression(addressOf.Expression); - var outputLabel = GenName(); + var outputName = GenVarName(); switch (addressOf.Expression.Type) { case NubPointerType: @@ -571,9 +602,9 @@ public class Generator case NubPrimitiveType { Kind: PrimitiveTypeKind.I64 }: case NubPrimitiveType { Kind: PrimitiveTypeKind.F64 }: case NubPrimitiveType { Kind: PrimitiveTypeKind.U64 }: - _builder.AppendLine($" %{outputLabel} =l alloc8 8"); - _builder.AppendLine($" storel {result}, %{outputLabel}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l alloc8 8"); + _builder.AppendLine($" storel {result}, %{outputName}"); + return $"%{outputName}"; case NubPrimitiveType { Kind: PrimitiveTypeKind.I32 }: case NubPrimitiveType { Kind: PrimitiveTypeKind.U32 }: case NubPrimitiveType { Kind: PrimitiveTypeKind.I16 }: @@ -581,9 +612,9 @@ public class Generator case NubPrimitiveType { Kind: PrimitiveTypeKind.I8 }: case NubPrimitiveType { Kind: PrimitiveTypeKind.U8 }: case NubPrimitiveType { Kind: PrimitiveTypeKind.F32 }: - _builder.AppendLine($" %{outputLabel} =l alloc8 4"); - _builder.AppendLine($" storew {result}, %{outputLabel}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l alloc8 4"); + _builder.AppendLine($" storew {result}, %{outputName}"); + return $"%{outputName}"; default: throw new ArgumentOutOfRangeException(); } @@ -593,7 +624,7 @@ public class Generator { var left = GenerateExpression(binaryExpression.Left); var right = GenerateExpression(binaryExpression.Right); - var outputLabel = GenName(); + var outputName = GenVarName(); switch (binaryExpression.Operator) { @@ -601,26 +632,26 @@ public class Generator { if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64)) { - _builder.AppendLine($" %{outputLabel} =w ceql {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w ceql {left}, {right}"); + return $"%{outputName}"; } if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32)) { - _builder.AppendLine($" %{outputLabel} =w ceqw {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w ceqw {left}, {right}"); + return $"%{outputName}"; } if (binaryExpression.Left.Type.Equals(NubPrimitiveType.String)) { - _builder.AppendLine($" %{outputLabel} =w call $nub_strcmp(l {left}, l {right})"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w call $nub_strcmp(l {left}, l {right})"); + return $"%{outputName}"; } if (binaryExpression.Left.Type.Equals(NubPrimitiveType.Bool)) { - _builder.AppendLine($" %{outputLabel} =w ceqw {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w ceqw {left}, {right}"); + return $"%{outputName}"; } break; @@ -629,27 +660,27 @@ public class Generator { if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64)) { - _builder.AppendLine($" %{outputLabel} =w cnel {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w cnel {left}, {right}"); + return $"%{outputName}"; } if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32)) { - _builder.AppendLine($" %{outputLabel} =w cnew {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w cnew {left}, {right}"); + return $"%{outputName}"; } if (binaryExpression.Left.Type.Equals(NubPrimitiveType.String)) { - _builder.AppendLine($" %{outputLabel} =w call $nub_strcmp(l {left}, l {right})"); - _builder.AppendLine($" %{outputLabel} =w xor %{outputLabel}, 1"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w call $nub_strcmp(l {left}, l {right})"); + _builder.AppendLine($" %{outputName} =w xor %{outputName}, 1"); + return $"%{outputName}"; } if (binaryExpression.Left.Type.Equals(NubPrimitiveType.Bool)) { - _builder.AppendLine($" %{outputLabel} =w cnew {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w cnew {left}, {right}"); + return $"%{outputName}"; } break; @@ -658,20 +689,20 @@ public class Generator { if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64)) { - _builder.AppendLine($" %{outputLabel} =w csgtl {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w csgtl {left}, {right}"); + return $"%{outputName}"; } if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32)) { - _builder.AppendLine($" %{outputLabel} =w csgtw {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w csgtw {left}, {right}"); + return $"%{outputName}"; } if (binaryExpression.Left.Type.Equals(NubPrimitiveType.Bool)) { - _builder.AppendLine($" %{outputLabel} =w csgtw {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w csgtw {left}, {right}"); + return $"%{outputName}"; } break; @@ -680,20 +711,20 @@ public class Generator { if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64)) { - _builder.AppendLine($" %{outputLabel} =w csgel {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w csgel {left}, {right}"); + return $"%{outputName}"; } if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32)) { - _builder.AppendLine($" %{outputLabel} =w csgew {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w csgew {left}, {right}"); + return $"%{outputName}"; } if (binaryExpression.Left.Type.Equals(NubPrimitiveType.Bool)) { - _builder.AppendLine($" %{outputLabel} =w csgew {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w csgew {left}, {right}"); + return $"%{outputName}"; } break; @@ -702,20 +733,20 @@ public class Generator { if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64)) { - _builder.AppendLine($" %{outputLabel} =w csltl {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w csltl {left}, {right}"); + return $"%{outputName}"; } if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32)) { - _builder.AppendLine($" %{outputLabel} =w csltw {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w csltw {left}, {right}"); + return $"%{outputName}"; } if (binaryExpression.Left.Type.Equals(NubPrimitiveType.Bool)) { - _builder.AppendLine($" %{outputLabel} =w csltw {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w csltw {left}, {right}"); + return $"%{outputName}"; } break; @@ -724,20 +755,20 @@ public class Generator { if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64)) { - _builder.AppendLine($" %{outputLabel} =w cslel {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w cslel {left}, {right}"); + return $"%{outputName}"; } if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32)) { - _builder.AppendLine($" %{outputLabel} =w cslew {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w cslew {left}, {right}"); + return $"%{outputName}"; } if (binaryExpression.Left.Type.Equals(NubPrimitiveType.Bool)) { - _builder.AppendLine($" %{outputLabel} =w cslew {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w cslew {left}, {right}"); + return $"%{outputName}"; } break; @@ -746,14 +777,14 @@ public class Generator { if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64)) { - _builder.AppendLine($" %{outputLabel} =l add {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l add {left}, {right}"); + return $"%{outputName}"; } if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32)) { - _builder.AppendLine($" %{outputLabel} =w add {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w add {left}, {right}"); + return $"%{outputName}"; } break; @@ -762,14 +793,14 @@ public class Generator { if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64)) { - _builder.AppendLine($" %{outputLabel} =l sub {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l sub {left}, {right}"); + return $"%{outputName}"; } if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32)) { - _builder.AppendLine($" %{outputLabel} =w sub {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w sub {left}, {right}"); + return $"%{outputName}"; } break; @@ -778,14 +809,14 @@ public class Generator { if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64)) { - _builder.AppendLine($" %{outputLabel} =l mul {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l mul {left}, {right}"); + return $"%{outputName}"; } if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32)) { - _builder.AppendLine($" %{outputLabel} =w mul {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w mul {left}, {right}"); + return $"%{outputName}"; } break; @@ -794,14 +825,14 @@ public class Generator { if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64)) { - _builder.AppendLine($" %{outputLabel} =l div {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l div {left}, {right}"); + return $"%{outputName}"; } if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32)) { - _builder.AppendLine($" %{outputLabel} =w div {left}, {right}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w div {left}, {right}"); + return $"%{outputName}"; } break; @@ -831,7 +862,7 @@ public class Generator throw new NotSupportedException("Casting is only supported for primitive types"); } - var outputLabel = GenName(); + var outputName = GenVarName(); switch (primitiveInputType.Kind) { @@ -849,14 +880,14 @@ public class Generator case PrimitiveTypeKind.U8: return input; case PrimitiveTypeKind.F64: - _builder.AppendLine($" %{outputLabel} =d sltof {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =d sltof {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.F32: - _builder.AppendLine($" %{outputLabel} =s sltof {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =s sltof {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.String: - _builder.AppendLine($" %{outputLabel} =l call $nub_i64_to_string(l {input})"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l call $nub_i64_to_string(l {input})"); + return $"%{outputName}"; case PrimitiveTypeKind.Bool: default: throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported"); @@ -866,8 +897,8 @@ public class Generator { case PrimitiveTypeKind.I64: case PrimitiveTypeKind.U64: - _builder.AppendLine($" %{outputLabel} =l extsw {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l extsw {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.I32: case PrimitiveTypeKind.U32: case PrimitiveTypeKind.I16: @@ -876,20 +907,20 @@ public class Generator case PrimitiveTypeKind.U8: return input; case PrimitiveTypeKind.F64: - var extLabel = GenName(); - _builder.AppendLine($" %{extLabel} =l extsw {input}"); - _builder.AppendLine($" %{outputLabel} =d sltof %{extLabel}"); - return $"%{outputLabel}"; + var extName = GenVarName(); + _builder.AppendLine($" %{extName} =l extsw {input}"); + _builder.AppendLine($" %{outputName} =d sltof %{extName}"); + return $"%{outputName}"; case PrimitiveTypeKind.F32: - _builder.AppendLine($" %{outputLabel} =s swtof {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =s swtof {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.String: - _builder.AppendLine($" %{outputLabel} =l call $nub_i32_to_string(w {input})"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l call $nub_i32_to_string(w {input})"); + return $"%{outputName}"; case PrimitiveTypeKind.Any: - var extAnyLabel = GenName(); - _builder.AppendLine($" %{extAnyLabel} =l extsw {input}"); - return $"%{extAnyLabel}"; + var extAnyName = GenVarName(); + _builder.AppendLine($" %{extAnyName} =l extsw {input}"); + return $"%{extAnyName}"; case PrimitiveTypeKind.Bool: default: throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported"); @@ -899,12 +930,12 @@ public class Generator { case PrimitiveTypeKind.I64: case PrimitiveTypeKind.U64: - _builder.AppendLine($" %{outputLabel} =l extsh {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l extsh {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.I32: case PrimitiveTypeKind.U32: - _builder.AppendLine($" %{outputLabel} =w extsh {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w extsh {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.I16: case PrimitiveTypeKind.U16: case PrimitiveTypeKind.I8: @@ -912,30 +943,30 @@ public class Generator return input; case PrimitiveTypeKind.F64: { - var extLabel = GenName(); - _builder.AppendLine($" %{extLabel} =l extsh {input}"); - _builder.AppendLine($" %{outputLabel} =d sltof %{extLabel}"); - return $"%{outputLabel}"; + var extName = GenVarName(); + _builder.AppendLine($" %{extName} =l extsh {input}"); + _builder.AppendLine($" %{outputName} =d sltof %{extName}"); + return $"%{outputName}"; } case PrimitiveTypeKind.F32: { - var extLabel = GenName(); - _builder.AppendLine($" %{extLabel} =w extsh {input}"); - _builder.AppendLine($" %{outputLabel} =s swtof %{extLabel}"); - return $"%{outputLabel}"; + var extName = GenVarName(); + _builder.AppendLine($" %{extName} =w extsh {input}"); + _builder.AppendLine($" %{outputName} =s swtof %{extName}"); + return $"%{outputName}"; } case PrimitiveTypeKind.String: { - var extLabel = GenName(); - _builder.AppendLine($" %{extLabel} =w extsh {input}"); - _builder.AppendLine($" %{outputLabel} =l call $nub_i32_to_string(w %{extLabel})"); - return $"%{outputLabel}"; + var extName = GenVarName(); + _builder.AppendLine($" %{extName} =w extsh {input}"); + _builder.AppendLine($" %{outputName} =l call $nub_i32_to_string(w %{extName})"); + return $"%{outputName}"; } case PrimitiveTypeKind.Any: { - var extLabel = GenName(); - _builder.AppendLine($" %{extLabel} =l extsh {input}"); - return $"%{extLabel}"; + var extName = GenVarName(); + _builder.AppendLine($" %{extName} =l extsh {input}"); + return $"%{extName}"; } case PrimitiveTypeKind.Bool: default: @@ -946,43 +977,43 @@ public class Generator { case PrimitiveTypeKind.I64: case PrimitiveTypeKind.U64: - _builder.AppendLine($" %{outputLabel} =l extsb {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l extsb {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.I32: case PrimitiveTypeKind.U32: case PrimitiveTypeKind.I16: case PrimitiveTypeKind.U16: - _builder.AppendLine($" %{outputLabel} =w extsb {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w extsb {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.I8: case PrimitiveTypeKind.U8: return input; case PrimitiveTypeKind.F64: { - var extLabel = GenName(); - _builder.AppendLine($" %{extLabel} =l extsb {input}"); - _builder.AppendLine($" %{outputLabel} =d sltof %{extLabel}"); - return $"%{outputLabel}"; + var extName = GenVarName(); + _builder.AppendLine($" %{extName} =l extsb {input}"); + _builder.AppendLine($" %{outputName} =d sltof %{extName}"); + return $"%{outputName}"; } case PrimitiveTypeKind.F32: { - var extLabel = GenName(); - _builder.AppendLine($" %{extLabel} =w extsb {input}"); - _builder.AppendLine($" %{outputLabel} =s swtof %{extLabel}"); - return $"%{outputLabel}"; + var extName = GenVarName(); + _builder.AppendLine($" %{extName} =w extsb {input}"); + _builder.AppendLine($" %{outputName} =s swtof %{extName}"); + return $"%{outputName}"; } case PrimitiveTypeKind.String: { - var extLabel = GenName(); - _builder.AppendLine($" %{extLabel} =w extsb {input}"); - _builder.AppendLine($" %{outputLabel} =l call $nub_i32_to_string(w %{extLabel})"); - return $"%{outputLabel}"; + var extName = GenVarName(); + _builder.AppendLine($" %{extName} =w extsb {input}"); + _builder.AppendLine($" %{outputName} =l call $nub_i32_to_string(w %{extName})"); + return $"%{outputName}"; } case PrimitiveTypeKind.Any: { - var extLabel = GenName(); - _builder.AppendLine($" %{extLabel} =l extsb {input}"); - return $"%{extLabel}"; + var extName = GenVarName(); + _builder.AppendLine($" %{extName} =l extsb {input}"); + return $"%{extName}"; } case PrimitiveTypeKind.Bool: default: @@ -1001,14 +1032,14 @@ public class Generator case PrimitiveTypeKind.U8: return input; case PrimitiveTypeKind.F64: - _builder.AppendLine($" %{outputLabel} =d ultof {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =d ultof {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.F32: - _builder.AppendLine($" %{outputLabel} =s ultof {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =s ultof {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.String: - _builder.AppendLine($" %{outputLabel} =l call $nub_u64_to_string(l {input})"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l call $nub_u64_to_string(l {input})"); + return $"%{outputName}"; case PrimitiveTypeKind.Any: return input; case PrimitiveTypeKind.Bool: @@ -1020,8 +1051,8 @@ public class Generator { case PrimitiveTypeKind.I64: case PrimitiveTypeKind.U64: - _builder.AppendLine($" %{outputLabel} =l extuw {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l extuw {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.I32: case PrimitiveTypeKind.U32: case PrimitiveTypeKind.I16: @@ -1030,20 +1061,20 @@ public class Generator case PrimitiveTypeKind.U8: return input; case PrimitiveTypeKind.F64: - var extLabel = GenName(); - _builder.AppendLine($" %{extLabel} =l extuw {input}"); - _builder.AppendLine($" %{outputLabel} =d ultof %{extLabel}"); - return $"%{outputLabel}"; + var extName = GenVarName(); + _builder.AppendLine($" %{extName} =l extuw {input}"); + _builder.AppendLine($" %{outputName} =d ultof %{extName}"); + return $"%{outputName}"; case PrimitiveTypeKind.F32: - _builder.AppendLine($" %{outputLabel} =s uwtof {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =s uwtof {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.String: - _builder.AppendLine($" %{outputLabel} =l call $nub_u32_to_string(w {input})"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l call $nub_u32_to_string(w {input})"); + return $"%{outputName}"; case PrimitiveTypeKind.Any: - var extAnyLabel = GenName(); - _builder.AppendLine($" %{extAnyLabel} =l extuw {input}"); - return $"%{extAnyLabel}"; + var extAnyName = GenVarName(); + _builder.AppendLine($" %{extAnyName} =l extuw {input}"); + return $"%{extAnyName}"; case PrimitiveTypeKind.Bool: default: throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported"); @@ -1053,12 +1084,12 @@ public class Generator { case PrimitiveTypeKind.I64: case PrimitiveTypeKind.U64: - _builder.AppendLine($" %{outputLabel} =l extuh {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l extuh {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.I32: case PrimitiveTypeKind.U32: - _builder.AppendLine($" %{outputLabel} =w extuh {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w extuh {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.I16: case PrimitiveTypeKind.U16: case PrimitiveTypeKind.I8: @@ -1066,30 +1097,30 @@ public class Generator return input; case PrimitiveTypeKind.F64: { - var extLabel = GenName(); - _builder.AppendLine($" %{extLabel} =l extuh {input}"); - _builder.AppendLine($" %{outputLabel} =d ultof %{extLabel}"); - return $"%{outputLabel}"; + var extName = GenVarName(); + _builder.AppendLine($" %{extName} =l extuh {input}"); + _builder.AppendLine($" %{outputName} =d ultof %{extName}"); + return $"%{outputName}"; } case PrimitiveTypeKind.F32: { - var extLabel = GenName(); - _builder.AppendLine($" %{extLabel} =w extuh {input}"); - _builder.AppendLine($" %{outputLabel} =s uwtof %{extLabel}"); - return $"%{outputLabel}"; + var extName = GenVarName(); + _builder.AppendLine($" %{extName} =w extuh {input}"); + _builder.AppendLine($" %{outputName} =s uwtof %{extName}"); + return $"%{outputName}"; } case PrimitiveTypeKind.String: { - var extLabel = GenName(); - _builder.AppendLine($" %{extLabel} =w extuh {input}"); - _builder.AppendLine($" %{outputLabel} =l call $nub_u32_to_string(w %{extLabel})"); - return $"%{outputLabel}"; + var extName = GenVarName(); + _builder.AppendLine($" %{extName} =w extuh {input}"); + _builder.AppendLine($" %{outputName} =l call $nub_u32_to_string(w %{extName})"); + return $"%{outputName}"; } case PrimitiveTypeKind.Any: { - var extLabel = GenName(); - _builder.AppendLine($" %{extLabel} =l extuh {input}"); - return $"%{extLabel}"; + var extName = GenVarName(); + _builder.AppendLine($" %{extName} =l extuh {input}"); + return $"%{extName}"; } case PrimitiveTypeKind.Bool: default: @@ -1100,43 +1131,43 @@ public class Generator { case PrimitiveTypeKind.I64: case PrimitiveTypeKind.U64: - _builder.AppendLine($" %{outputLabel} =l extub {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l extub {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.I32: case PrimitiveTypeKind.U32: case PrimitiveTypeKind.I16: case PrimitiveTypeKind.U16: - _builder.AppendLine($" %{outputLabel} =w extub {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w extub {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.I8: case PrimitiveTypeKind.U8: return input; case PrimitiveTypeKind.F64: { - var extLabel = GenName(); - _builder.AppendLine($" %{extLabel} =l extub {input}"); - _builder.AppendLine($" %{outputLabel} =d ultof %{extLabel}"); - return $"%{outputLabel}"; + var extName = GenVarName(); + _builder.AppendLine($" %{extName} =l extub {input}"); + _builder.AppendLine($" %{outputName} =d ultof %{extName}"); + return $"%{outputName}"; } case PrimitiveTypeKind.F32: { - var extLabel = GenName(); - _builder.AppendLine($" %{extLabel} =w extub {input}"); - _builder.AppendLine($" %{outputLabel} =s uwtof %{extLabel}"); - return $"%{outputLabel}"; + var extName = GenVarName(); + _builder.AppendLine($" %{extName} =w extub {input}"); + _builder.AppendLine($" %{outputName} =s uwtof %{extName}"); + return $"%{outputName}"; } case PrimitiveTypeKind.String: { - var extLabel = GenName(); - _builder.AppendLine($" %{extLabel} =w extub {input}"); - _builder.AppendLine($" %{outputLabel} =l call $nub_u32_to_string(w %{extLabel})"); - return $"%{outputLabel}"; + var extName = GenVarName(); + _builder.AppendLine($" %{extName} =w extub {input}"); + _builder.AppendLine($" %{outputName} =l call $nub_u32_to_string(w %{extName})"); + return $"%{outputName}"; } case PrimitiveTypeKind.Any: { - var extLabel = GenName(); - _builder.AppendLine($" %{extLabel} =l extub {input}"); - return $"%{extLabel}"; + var extName = GenVarName(); + _builder.AppendLine($" %{extName} =l extub {input}"); + return $"%{extName}"; } case PrimitiveTypeKind.Bool: default: @@ -1149,27 +1180,27 @@ public class Generator case PrimitiveTypeKind.Any: return input; case PrimitiveTypeKind.F32: - _builder.AppendLine($" %{outputLabel} =s dtos {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =s dtos {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.I64: - _builder.AppendLine($" %{outputLabel} =l dtosi {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l dtosi {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.I32: case PrimitiveTypeKind.I16: case PrimitiveTypeKind.I8: - _builder.AppendLine($" %{outputLabel} =w dtosi {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w dtosi {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.U64: - _builder.AppendLine($" %{outputLabel} =l dtoui {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l dtoui {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.U32: case PrimitiveTypeKind.U16: case PrimitiveTypeKind.U8: - _builder.AppendLine($" %{outputLabel} =w dtoui {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w dtoui {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.String: - _builder.AppendLine($" %{outputLabel} =l call $nub_f64_to_string(d {input})"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l call $nub_f64_to_string(d {input})"); + return $"%{outputName}"; case PrimitiveTypeKind.Bool: default: throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported"); @@ -1178,29 +1209,29 @@ public class Generator switch (primitiveOutputType.Kind) { case PrimitiveTypeKind.F64: - _builder.AppendLine($" %{outputLabel} =d stod {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =d stod {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.F32: return input; case PrimitiveTypeKind.I64: - _builder.AppendLine($" %{outputLabel} =l stosi {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l stosi {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.I32: case PrimitiveTypeKind.I16: case PrimitiveTypeKind.I8: - _builder.AppendLine($" %{outputLabel} =w stosi {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w stosi {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.U64: - _builder.AppendLine($" %{outputLabel} =l stoui {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l stoui {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.U32: case PrimitiveTypeKind.U16: case PrimitiveTypeKind.U8: - _builder.AppendLine($" %{outputLabel} =w stoui {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w stoui {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.String: - _builder.AppendLine($" %{outputLabel} =l call $nub_f32_to_string(s {input})"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l call $nub_f32_to_string(s {input})"); + return $"%{outputName}"; case PrimitiveTypeKind.Any: throw new NotImplementedException(); case PrimitiveTypeKind.Bool: @@ -1213,11 +1244,11 @@ public class Generator case PrimitiveTypeKind.Bool: return input; case PrimitiveTypeKind.Any: - _builder.AppendLine($" %{outputLabel} =l extsw {input}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l extsw {input}"); + return $"%{outputName}"; case PrimitiveTypeKind.String: - _builder.AppendLine($" %{outputLabel} =l call $nub_bool_to_string(s {input})"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l call $nub_bool_to_string(s {input})"); + return $"%{outputName}"; case PrimitiveTypeKind.I64: case PrimitiveTypeKind.I32: case PrimitiveTypeKind.I16: @@ -1261,9 +1292,9 @@ public class Generator private string GenerateIdentifier(IdentifierNode identifier) { var variable = _variables[identifier.Identifier]; - var outputLabel = GenName(); - _builder.AppendLine($" %{outputLabel} ={SQT(identifier.Type)} load{SQT(identifier.Type)} {variable.Pointer}"); - return $"%{outputLabel}"; + var outputName = GenVarName(); + _builder.AppendLine($" %{outputName} ={SQT(identifier.Type)} load{SQT(identifier.Type)} {variable.Pointer}"); + return $"%{outputName}"; } private string GenerateLiteral(LiteralNode literal) @@ -1302,7 +1333,7 @@ public class Generator throw new Exception($"Struct {structInitializer.StructType.Name} is not defined"); } - var structVar = GenName(); + var structVar = GenVarName(); var size = structDefinition.Fields.Sum(x => QbeTypeSize(x.Type)); _builder.AppendLine($" %{structVar} =l alloc8 {size}"); @@ -1314,16 +1345,16 @@ public class Generator if (structInitializer.Initializers.TryGetValue(field.Name, out var fieldValue)) { var var = GenerateExpression(fieldValue); - var offsetLabel = GenName(); - _builder.AppendLine($" %{offsetLabel} =l add %{structVar}, {i * QbeTypeSize(field.Type)}"); - _builder.AppendLine($" store{SQT(field.Type)} {var}, %{offsetLabel}"); + var offsetName = GenVarName(); + _builder.AppendLine($" %{offsetName} =l add %{structVar}, {i * QbeTypeSize(field.Type)}"); + _builder.AppendLine($" store{SQT(field.Type)} {var}, %{offsetName}"); } else if (field.Value.HasValue) { var var = GenerateExpression(field.Value.Value); - var offsetLabel = GenName(); - _builder.AppendLine($" %{offsetLabel} =l add %{structVar}, {i * QbeTypeSize(field.Type)}"); - _builder.AppendLine($" store{SQT(field.Type)} {var}, %{offsetLabel}"); + var offsetName = GenVarName(); + _builder.AppendLine($" %{offsetName} =l add %{structVar}, {i * QbeTypeSize(field.Type)}"); + _builder.AppendLine($" store{SQT(field.Type)} {var}, %{offsetName}"); } else { @@ -1337,7 +1368,7 @@ public class Generator private string GenerateUnaryExpression(UnaryExpressionNode unaryExpression) { var operand = GenerateExpression(unaryExpression.Operand); - var outputLabel = GenName(); + var outputName = GenVarName(); switch (unaryExpression.Operator) { @@ -1346,17 +1377,17 @@ public class Generator switch (unaryExpression.Operand.Type) { case NubPrimitiveType { Kind: PrimitiveTypeKind.I64 }: - _builder.AppendLine($" %{outputLabel} =l neg {operand}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =l neg {operand}"); + return $"%{outputName}"; case NubPrimitiveType { Kind: PrimitiveTypeKind.I32 or PrimitiveTypeKind.I16 or PrimitiveTypeKind.I8 }: - _builder.AppendLine($" %{outputLabel} =w neg {operand}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w neg {operand}"); + return $"%{outputName}"; case NubPrimitiveType { Kind: PrimitiveTypeKind.F64 }: - _builder.AppendLine($" %{outputLabel} =d neg {operand}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =d neg {operand}"); + return $"%{outputName}"; case NubPrimitiveType { Kind: PrimitiveTypeKind.F32 }: - _builder.AppendLine($" %{outputLabel} =s neg {operand}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =s neg {operand}"); + return $"%{outputName}"; } break; @@ -1366,8 +1397,8 @@ public class Generator switch (unaryExpression.Operand.Type) { case NubPrimitiveType { Kind: PrimitiveTypeKind.Bool }: - _builder.AppendLine($" %{outputLabel} =w xor {operand}, 1"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} =w xor {operand}, 1"); + return $"%{outputName}"; } break; @@ -1391,9 +1422,9 @@ public class Generator { if (memberAccess.Member == "count") { - var outputLabel = GenName(); - _builder.AppendLine($" %{outputLabel} =l loadl {expression}"); - return $"%{outputLabel}"; + var outputName = GenVarName(); + _builder.AppendLine($" %{outputName} =l loadl {expression}"); + return $"%{outputName}"; } break; @@ -1421,13 +1452,13 @@ public class Generator throw new Exception($"Field {memberAccess.Member} is not defined in struct {structType.Name}"); } - var offsetLabel = GenName(); - _builder.AppendLine($" %{offsetLabel} =l add {expression}, {fieldIndex * QbeTypeSize(memberAccess.Type)}"); + var offsetName = GenVarName(); + _builder.AppendLine($" %{offsetName} =l add {expression}, {fieldIndex * QbeTypeSize(memberAccess.Type)}"); - var outputLabel = GenName(); - _builder.AppendLine($" %{outputLabel} ={SQT(memberAccess.Type)} load{SQT(memberAccess.Type)} %{offsetLabel}"); + var outputName = GenVarName(); + _builder.AppendLine($" %{outputName} ={SQT(memberAccess.Type)} load{SQT(memberAccess.Type)} %{offsetName}"); - return $"%{outputLabel}"; + return $"%{outputName}"; } } @@ -1436,16 +1467,26 @@ public class Generator private string GenerateExpressionFuncCall(FuncCallExpressionNode funcCall) { - var outputLabel = GenName(); + var outputName = GenVarName(); var call = GenerateFuncCall(funcCall.FuncCall); - _builder.AppendLine($" %{outputLabel} ={SQT(funcCall.Type)} {call}"); - return $"%{outputLabel}"; + _builder.AppendLine($" %{outputName} ={SQT(funcCall.Type)} {call}"); + return $"%{outputName}"; } - private string GenName() + private string GenVarName() { return $"v{++_variableIndex}"; } + + private string GenFuncName() + { + return $"f{++_funcIndex}"; + } + + private string GenLabelName() + { + return $"l{++_labelIndex}"; + } private IFuncSignature? LookupFuncSignature(string @namespace, string name, List parameters) { diff --git a/src/compiler/Nub.Lang/Frontend/Lexing/Lexer.cs b/src/compiler/Nub.Lang/Frontend/Lexing/Lexer.cs index 95ad60b..891b496 100644 --- a/src/compiler/Nub.Lang/Frontend/Lexing/Lexer.cs +++ b/src/compiler/Nub.Lang/Frontend/Lexing/Lexer.cs @@ -21,7 +21,7 @@ public class Lexer private static readonly Dictionary Modifiers = new() { - ["global"] = Modifier.Global, + ["export"] = Modifier.Export, ["extern"] = Modifier.Extern, }; diff --git a/src/compiler/Nub.Lang/Frontend/Lexing/ModifierToken.cs b/src/compiler/Nub.Lang/Frontend/Lexing/ModifierToken.cs index a6651a0..4170ea8 100644 --- a/src/compiler/Nub.Lang/Frontend/Lexing/ModifierToken.cs +++ b/src/compiler/Nub.Lang/Frontend/Lexing/ModifierToken.cs @@ -10,5 +10,5 @@ public class ModifierToken(SourceText sourceText, int startIndex, int endIndex, public enum Modifier { Extern, - Global + Export } \ No newline at end of file diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/FuncDefinitionNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/FuncDefinitionNode.cs index de24b0c..c139f2e 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/FuncDefinitionNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/FuncDefinitionNode.cs @@ -52,13 +52,13 @@ public interface IFuncSignature public string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){(ReturnType.HasValue ? ": " + ReturnType.Value : "")}"; } -public class LocalFuncDefinitionNode(IReadOnlyList tokens, Optional documentation, string name, List parameters, BlockNode body, Optional returnType, bool global) : DefinitionNode(tokens, documentation), IFuncSignature +public class LocalFuncDefinitionNode(IReadOnlyList tokens, Optional documentation, string name, List parameters, BlockNode body, Optional returnType, bool exported) : DefinitionNode(tokens, documentation), IFuncSignature { public string Name { get; } = name; public List Parameters { get; } = parameters; public BlockNode Body { get; } = body; public Optional ReturnType { get; } = returnType; - public bool Global { get; } = global; + public bool Exported { get; } = exported; public override string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){(ReturnType.HasValue ? ": " + ReturnType.Value : "")}"; } diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/Parser.cs b/src/compiler/Nub.Lang/Frontend/Parsing/Parser.cs index d2ded08..ce4d182 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/Parser.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/Parser.cs @@ -117,7 +117,7 @@ public class Parser } var body = ParseBlock(); - var isGlobal = modifiers.RemoveAll(x => x.Modifier == Modifier.Global) > 0; + var exported = modifiers.RemoveAll(x => x.Modifier == Modifier.Export) > 0; if (modifiers.Count != 0) { @@ -128,7 +128,7 @@ public class Parser .Build()); } - return new LocalFuncDefinitionNode(GetTokensForNode(startIndex), documentation, name.Value, parameters, body, returnType, isGlobal); + return new LocalFuncDefinitionNode(GetTokensForNode(startIndex), documentation, name.Value, parameters, body, returnType, exported); } private StructDefinitionNode ParseStruct(int startIndex, List _, Optional documentation) @@ -414,6 +414,7 @@ public class Parser { case SymbolToken { Symbol: Symbol.DoubleColon }: { + Next(); var name = ExpectIdentifier(); ExpectSymbol(Symbol.OpenParen); var parameters = new List(); @@ -435,6 +436,7 @@ public class Parser } case SymbolToken { Symbol: Symbol.OpenParen }: { + Next(); var parameters = new List(); while (!TryExpectSymbol(Symbol.CloseParen)) { diff --git a/src/compiler/Nub.Lang/Frontend/Typing/TypeChecker.cs b/src/compiler/Nub.Lang/Frontend/Typing/TypeChecker.cs index e7978ff..7c4f32c 100644 --- a/src/compiler/Nub.Lang/Frontend/Typing/TypeChecker.cs +++ b/src/compiler/Nub.Lang/Frontend/Typing/TypeChecker.cs @@ -19,16 +19,27 @@ public class TypeChecker _hasReturnStatement = false; _sourceFiles = sourceFiles; - var externFunctionNames = _sourceFiles + var externFuncDefinitions = _sourceFiles .SelectMany(f => f.Definitions) .OfType() .ToArray(); - foreach (var funcName in externFunctionNames.Where(x => externFunctionNames.Count(y => x.Name == y.Name) > 1)) + foreach (var funcName in externFuncDefinitions.Where(x => externFuncDefinitions.Count(y => x.Name == y.Name) > 1)) { ReportError($"Extern function '{funcName}' has been declared more than once", funcName); } + var exportedLocalFuncDefinitions = _sourceFiles + .SelectMany(f => f.Definitions) + .OfType() + .Where(f => f.Exported) + .ToArray(); + + foreach (var funcName in exportedLocalFuncDefinitions.Where(x => exportedLocalFuncDefinitions.Count(y => x.Name == y.Name) > 1)) + { + ReportError($"Exported function '{funcName}' has been declared more than once", funcName); + } + foreach (var structDef in _sourceFiles.SelectMany(f => f.Definitions).OfType()) { TypeCheckStructDef(structDef); diff --git a/src/compiler/Nub.Lang/Program.cs b/src/compiler/Nub.Lang/Program.cs index 1d54320..4dd96bb 100644 --- a/src/compiler/Nub.Lang/Program.cs +++ b/src/compiler/Nub.Lang/Program.cs @@ -58,11 +58,13 @@ internal static class Program typeCheckResult.PrintAllDiagnostics(); error = error || typeCheckResult.HasErrors; + if (error) return 1; + var generator = new Generator(); var result = generator.Generate(files); Console.Out.Write(result); - return error ? 1 : 0; + return 0; } } \ No newline at end of file