...
This commit is contained in:
@@ -71,10 +71,10 @@ var objectPaths = new List<string>();
|
||||
foreach (var cPath in cPaths)
|
||||
{
|
||||
var objectPath = Path.ChangeExtension(cPath, "o");
|
||||
using var compileProcess = Process.Start("gcc", [
|
||||
"-ffreestanding", "-nostartfiles", "-std=c23",
|
||||
"-g", "-lm",
|
||||
"-c", "-o", objectPath,
|
||||
using var compileProcess = Process.Start("clang", [
|
||||
"-ffreestanding", "-std=c23",
|
||||
"-g", "-c",
|
||||
"-o", objectPath,
|
||||
cPath,
|
||||
]);
|
||||
|
||||
@@ -82,79 +82,13 @@ foreach (var cPath in cPaths)
|
||||
|
||||
if (compileProcess.ExitCode != 0)
|
||||
{
|
||||
Console.Error.WriteLine($"gcc failed with exit code {compileProcess.ExitCode}");
|
||||
Console.Error.WriteLine($"clang failed with exit code {compileProcess.ExitCode}");
|
||||
return 1;
|
||||
}
|
||||
|
||||
objectPaths.Add(objectPath);
|
||||
}
|
||||
|
||||
if (modules.TryGetValue("main", out var mainModule))
|
||||
{
|
||||
var mainFunction = mainModule
|
||||
.Functions(true)
|
||||
.FirstOrDefault(x => x.Prototype.ExternSymbol == "main");
|
||||
|
||||
if (mainFunction is { Prototype.ExternSymbol: not null })
|
||||
{
|
||||
var runtime = $"""
|
||||
.intel_syntax noprefix
|
||||
|
||||
.text
|
||||
.globl _start
|
||||
_start:
|
||||
mov rdi, [rsp] # argc
|
||||
mov rsi, [rsp + 8] # argv
|
||||
call {mainFunction.Prototype.ExternSymbol}
|
||||
mov rdi, rax # Move return value into rdi
|
||||
mov rax, 60 # syscall: exit
|
||||
syscall
|
||||
|
||||
""";
|
||||
|
||||
var runtimePath = Path.Combine(".build", "runtime.s");
|
||||
File.WriteAllText(runtimePath, runtime);
|
||||
|
||||
using var assembleProcess = Process.Start(new ProcessStartInfo("as", ["-g", "-c", runtimePath, "-o", Path.Combine(".build", "runtime.o")]));
|
||||
if (assembleProcess == null) return 1;
|
||||
assembleProcess.WaitForExit();
|
||||
|
||||
if (assembleProcess.ExitCode != 0)
|
||||
{
|
||||
Console.Error.WriteLine($"gcc failed with exit code {assembleProcess.ExitCode}");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (assembleProcess.ExitCode != 0) return 1;
|
||||
|
||||
using var linkProcess = Process.Start(new ProcessStartInfo("gcc", [
|
||||
"-ffreestanding", "-nostartfiles", "-std=c23",
|
||||
"-g", "-lm",
|
||||
"-o", Path.Combine(".build", "out"),
|
||||
..objectPaths,
|
||||
Path.Combine(".build", "runtime.o"),
|
||||
..objectFileArgs
|
||||
]));
|
||||
|
||||
if (linkProcess == null) return 1;
|
||||
linkProcess.WaitForExit();
|
||||
|
||||
if (linkProcess.ExitCode != 0)
|
||||
{
|
||||
Console.Error.WriteLine($"gcc failed with exit code {linkProcess.ExitCode}");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Console.WriteLine("Build successful: .build/out");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("No main function found in module main, skipping link step");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("No main function found in module main, skipping link step");
|
||||
}
|
||||
Console.Out.WriteLine(string.Join(' ', objectPaths));
|
||||
|
||||
return 0;
|
||||
@@ -100,20 +100,14 @@ public record UnaryExpressionNode(List<Token> Tokens, NubType Type, UnaryOperato
|
||||
|
||||
public record FuncCallNode(List<Token> Tokens, NubType Type, ExpressionNode Expression, List<ExpressionNode> Parameters) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record LValueIdentifierNode(List<Token> Tokens, NubType Type, string Name) : LValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record RValueIdentifierNode(List<Token> Tokens, NubType Type, string Name) : RValueExpressionNode(Tokens, Type);
|
||||
public record VariableIdentifierNode(List<Token> Tokens, NubType Type, string Name) : LValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record FuncIdentifierNode(List<Token> Tokens, NubType Type, string Module, string Name, string? ExternSymbol) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record ArrayInitializerNode(List<Token> Tokens, NubType Type, ExpressionNode Capacity, NubType ElementType) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record ConstArrayInitializerNode(List<Token> Tokens, NubType Type, long Capacity, NubType ElementType) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record ArrayIndexAccessNode(List<Token> Tokens, NubType Type, ExpressionNode Target, ExpressionNode Index) : LValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record ConstArrayIndexAccessNode(List<Token> Tokens, NubType Type, ExpressionNode Target, ExpressionNode Index) : LValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record SliceIndexAccessNode(List<Token> Tokens, NubType Type, ExpressionNode Target, ExpressionNode Index) : LValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record AddressOfNode(List<Token> Tokens, NubType Type, LValueExpressionNode LValue) : RValueExpressionNode(Tokens, Type);
|
||||
@@ -128,7 +122,9 @@ public record ConvertIntNode(List<Token> Tokens, NubType Type, ExpressionNode Va
|
||||
|
||||
public record ConvertFloatNode(List<Token> Tokens, NubType Type, ExpressionNode Value, NubFloatType ValueType, NubFloatType TargetType) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
// public record ConvertConstArrayToArrayNode(List<Token> Tokens, NubType Type, ExpressionNode Value) : RValueExpressionNode(Tokens, Type);
|
||||
public record ConvertStringToCStringNode(List<Token> Tokens, ExpressionNode Value) : RValueExpressionNode(Tokens, new NubCStringType());
|
||||
|
||||
public record ConvertCStringToStringNode(List<Token> Tokens, ExpressionNode Value) : RValueExpressionNode(Tokens, new NubStringType());
|
||||
|
||||
public record SizeBuiltinNode(List<Token> Tokens, NubType Type, NubType TargetType) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ public sealed class TypeChecker
|
||||
|
||||
foreach (var (name, module) in _importedModules)
|
||||
{
|
||||
foreach (var structSyntax in module.Structs(false))
|
||||
foreach (var structSyntax in module.Structs(true))
|
||||
{
|
||||
var fields = structSyntax.Fields
|
||||
.Select(f => new NubStructFieldType(f.Name, ResolveType(f.Type), f.Value != null))
|
||||
@@ -63,7 +63,7 @@ public sealed class TypeChecker
|
||||
importedStructTypes.Add(new NubStructType(name, structSyntax.Name, fields));
|
||||
}
|
||||
|
||||
foreach (var funcSyntax in module.Functions(false))
|
||||
foreach (var funcSyntax in module.Functions(true))
|
||||
{
|
||||
importedFunctions.Add(CheckFuncPrototype(funcSyntax.Prototype));
|
||||
}
|
||||
@@ -109,7 +109,7 @@ public sealed class TypeChecker
|
||||
{
|
||||
foreach (var parameter in node.Prototype.Parameters)
|
||||
{
|
||||
CurrentScope.DeclareVariable(new Variable(parameter.Name, ResolveType(parameter.Type), VariableKind.RValue));
|
||||
CurrentScope.DeclareVariable(new Variable(parameter.Name, ResolveType(parameter.Type)));
|
||||
}
|
||||
|
||||
var prototype = CheckFuncPrototype(node.Prototype);
|
||||
@@ -211,7 +211,7 @@ public sealed class TypeChecker
|
||||
throw new TypeCheckerException(Diagnostic.Error($"Cannot infer type of variable {statement.Name}").At(statement).Build());
|
||||
}
|
||||
|
||||
CurrentScope.DeclareVariable(new Variable(statement.Name, type, VariableKind.LValue));
|
||||
CurrentScope.DeclareVariable(new Variable(statement.Name, type));
|
||||
|
||||
return new VariableDeclarationNode(statement.Tokens, statement.Name, assignmentNode, type);
|
||||
}
|
||||
@@ -248,7 +248,6 @@ public sealed class TypeChecker
|
||||
LocalIdentifierSyntax expression => CheckLocalIdentifier(expression),
|
||||
ModuleIdentifierSyntax expression => CheckModuleIdentifier(expression),
|
||||
BoolLiteralSyntax expression => CheckBoolLiteral(expression),
|
||||
ConstArrayInitializerSyntax expression => CheckConstArrayInitializer(expression),
|
||||
StringLiteralSyntax expression => CheckStringLiteral(expression, expectedType),
|
||||
IntLiteralSyntax expression => CheckIntLiteral(expression, expectedType),
|
||||
FloatLiteralSyntax expression => CheckFloatLiteral(expression, expectedType),
|
||||
@@ -265,10 +264,15 @@ public sealed class TypeChecker
|
||||
return result;
|
||||
}
|
||||
|
||||
// if (result.Type is NubConstArrayType && expectedType is NubArrayType)
|
||||
// {
|
||||
// return new ConvertConstArrayToArrayNode(node.Tokens, expectedType, result);
|
||||
// }
|
||||
if (result.Type is NubStringType && expectedType is NubCStringType)
|
||||
{
|
||||
return new ConvertStringToCStringNode(node.Tokens, result);
|
||||
}
|
||||
|
||||
if (result.Type is NubCStringType && expectedType is NubStringType)
|
||||
{
|
||||
return new ConvertCStringToStringNode(node.Tokens, result);
|
||||
}
|
||||
|
||||
if (result.Type is NubIntType sourceIntType && expectedType is NubIntType targetIntType)
|
||||
{
|
||||
@@ -289,13 +293,6 @@ public sealed class TypeChecker
|
||||
throw new TypeCheckerException(Diagnostic.Error($"Cannot convert {result.Type} to {expectedType}").At(node).Build());
|
||||
}
|
||||
|
||||
private ConstArrayInitializerNode CheckConstArrayInitializer(ConstArrayInitializerSyntax expression)
|
||||
{
|
||||
var elementType = ResolveType(expression.ElementType);
|
||||
var type = new NubConstArrayType(elementType, expression.Capacity);
|
||||
return new ConstArrayInitializerNode(expression.Tokens, type, expression.Capacity, elementType);
|
||||
}
|
||||
|
||||
private FloatToIntBuiltinNode CheckFloatToInt(FloatToIntBuiltinSyntax expression)
|
||||
{
|
||||
var value = CheckExpression(expression.Value);
|
||||
@@ -333,13 +330,20 @@ public sealed class TypeChecker
|
||||
|
||||
private ExpressionNode CheckArrayIndexAccess(ArrayIndexAccessSyntax expression)
|
||||
{
|
||||
var index = CheckExpression(expression.Index, new NubIntType(false, 64));
|
||||
var index = CheckExpression(expression.Index);
|
||||
if (index.Type is not NubIntType)
|
||||
{
|
||||
throw new TypeCheckerException(Diagnostic
|
||||
.Error("Array indexer must be of type int")
|
||||
.At(expression.Index)
|
||||
.Build());
|
||||
}
|
||||
|
||||
var target = CheckExpression(expression.Target);
|
||||
|
||||
return target.Type switch
|
||||
{
|
||||
NubArrayType arrayType => new ArrayIndexAccessNode(expression.Tokens, arrayType.ElementType, target, index),
|
||||
NubConstArrayType constArrayType => new ConstArrayIndexAccessNode(expression.Tokens, constArrayType.ElementType, target, index),
|
||||
NubSliceType sliceType => new SliceIndexAccessNode(expression.Tokens, sliceType.ElementType, target, index),
|
||||
_ => throw new TypeCheckerException(Diagnostic.Error($"Cannot use array indexer on type {target.Type}").At(expression).Build())
|
||||
};
|
||||
@@ -581,12 +585,7 @@ public sealed class TypeChecker
|
||||
var scopeIdent = CurrentScope.LookupVariable(expression.Name);
|
||||
if (scopeIdent != null)
|
||||
{
|
||||
return scopeIdent.Kind switch
|
||||
{
|
||||
VariableKind.LValue => new LValueIdentifierNode(expression.Tokens, scopeIdent.Type, expression.Name),
|
||||
VariableKind.RValue => new RValueIdentifierNode(expression.Tokens, scopeIdent.Type, expression.Name),
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
return new VariableIdentifierNode(expression.Tokens, scopeIdent.Type, expression.Name);
|
||||
}
|
||||
|
||||
var module = _importedModules[CurrentScope.Module];
|
||||
@@ -635,7 +634,7 @@ public sealed class TypeChecker
|
||||
{
|
||||
NubCStringType => new CStringLiteralNode(expression.Tokens, expectedType, expression.Value),
|
||||
NubStringType => new StringLiteralNode(expression.Tokens, expectedType, expression.Value),
|
||||
_ => new CStringLiteralNode(expression.Tokens, new NubCStringType(), expression.Value)
|
||||
_ => new StringLiteralNode(expression.Tokens, new NubStringType(), expression.Value)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -894,13 +893,7 @@ public sealed class TypeChecker
|
||||
}
|
||||
}
|
||||
|
||||
public enum VariableKind
|
||||
{
|
||||
LValue,
|
||||
RValue
|
||||
}
|
||||
|
||||
public record Variable(string Name, NubType Type, VariableKind Kind);
|
||||
public record Variable(string Name, NubType Type);
|
||||
|
||||
public class Scope(string module, Scope? parent = null)
|
||||
{
|
||||
|
||||
@@ -14,6 +14,8 @@ public static class CType
|
||||
NubFloatType floatType => CreateFloatType(floatType, variableName),
|
||||
NubCStringType => "char*" + (variableName != null ? $" {variableName}" : ""),
|
||||
NubPointerType ptr => CreatePointerType(ptr, variableName),
|
||||
NubSliceType nubSliceType => "slice" + (variableName != null ? $" {variableName}" : ""),
|
||||
NubStringType nubStringType => "string" + (variableName != null ? $" {variableName}" : ""),
|
||||
NubConstArrayType arr => CreateConstArrayType(arr, variableName),
|
||||
NubArrayType arr => CreateArrayType(arr, variableName),
|
||||
NubFuncType fn => CreateFuncType(fn, variableName),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Text;
|
||||
using NubLang.Ast;
|
||||
using NubLang.Syntax;
|
||||
|
||||
@@ -39,6 +40,21 @@ public class Generator
|
||||
_writer.WriteLine("#include <stddef.h>");
|
||||
_writer.WriteLine();
|
||||
|
||||
_writer.WriteLine("""
|
||||
typedef struct
|
||||
{
|
||||
size_t length;
|
||||
uint8_t *data;
|
||||
} string;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t length;
|
||||
void *data;
|
||||
} slice;
|
||||
|
||||
""");
|
||||
|
||||
foreach (var structType in _compilationUnit.ImportedStructTypes)
|
||||
{
|
||||
_writer.WriteLine("typedef struct");
|
||||
@@ -68,22 +84,6 @@ public class Generator
|
||||
_writer.WriteLine();
|
||||
}
|
||||
|
||||
// note(nub31): declare extern functions
|
||||
foreach (var funcNode in _compilationUnit.Functions)
|
||||
{
|
||||
if (funcNode.Body != null) continue;
|
||||
|
||||
EmitLine(funcNode.Tokens.FirstOrDefault());
|
||||
var parameters = funcNode.Prototype.Parameters.Count != 0
|
||||
? string.Join(", ", funcNode.Prototype.Parameters.Select(x => CType.Create(x.Type, x.Name)))
|
||||
: "void";
|
||||
|
||||
var name = FuncName(funcNode.Module, funcNode.Name, funcNode.Prototype.ExternSymbol);
|
||||
_writer.WriteLine($"{CType.Create(funcNode.Prototype.ReturnType, name)}({parameters});");
|
||||
}
|
||||
|
||||
_writer.WriteLine();
|
||||
|
||||
// note(nub31): Normal functions
|
||||
foreach (var funcNode in _compilationUnit.Functions)
|
||||
{
|
||||
@@ -94,11 +94,6 @@ public class Generator
|
||||
? string.Join(", ", funcNode.Prototype.Parameters.Select(x => CType.Create(x.Type, x.Name)))
|
||||
: "void";
|
||||
|
||||
if (funcNode.Prototype.ExternSymbol == null)
|
||||
{
|
||||
_writer.Write("static ");
|
||||
}
|
||||
|
||||
var name = FuncName(funcNode.Module, funcNode.Name, funcNode.Prototype.ExternSymbol);
|
||||
_writer.WriteLine($"{CType.Create(funcNode.Prototype.ReturnType, name)}({parameters})");
|
||||
EmitBlock(funcNode.Body);
|
||||
@@ -165,11 +160,13 @@ public class Generator
|
||||
|
||||
private void EmitBreak(BreakNode _)
|
||||
{
|
||||
// todo(nub31): Emit deferred statements
|
||||
_writer.WriteLine("break;");
|
||||
}
|
||||
|
||||
private void EmitContinue(ContinueNode _)
|
||||
{
|
||||
// todo(nub31): Emit deferred statements
|
||||
_writer.WriteLine("continue;");
|
||||
}
|
||||
|
||||
@@ -265,38 +262,31 @@ public class Generator
|
||||
ArrayIndexAccessNode arrayIndexAccessNode => EmitArrayIndexAccess(arrayIndexAccessNode),
|
||||
ArrayInitializerNode arrayInitializerNode => EmitArrayInitializer(arrayInitializerNode),
|
||||
BinaryExpressionNode binaryExpressionNode => EmitBinaryExpression(binaryExpressionNode),
|
||||
BoolLiteralNode boolLiteralNode => EmitBoolLiteral(boolLiteralNode),
|
||||
ConstArrayIndexAccessNode constArrayIndexAccessNode => EmitConstArrayIndexAccess(constArrayIndexAccessNode),
|
||||
ConstArrayInitializerNode constArrayInitializerNode => EmitConstArrayInitializer(constArrayInitializerNode),
|
||||
// ConvertConstArrayToArrayNode convertConstArrayToArrayNode => EmitConvertConstArrayToArray(convertConstArrayToArrayNode),
|
||||
BoolLiteralNode boolLiteralNode => boolLiteralNode.Value ? "true" : "false",
|
||||
ConvertCStringToStringNode convertCStringToStringNode => EmitConvertCStringToString(convertCStringToStringNode),
|
||||
ConvertFloatNode convertFloatNode => EmitConvertFloat(convertFloatNode),
|
||||
ConvertIntNode convertIntNode => EmitConvertInt(convertIntNode),
|
||||
CStringLiteralNode cStringLiteralNode => EmitCStringLiteral(cStringLiteralNode),
|
||||
ConvertStringToCStringNode convertStringToCStringNode => EmitConvertStringToCString(convertStringToCStringNode),
|
||||
CStringLiteralNode cStringLiteralNode => $"\"{cStringLiteralNode.Value}\"",
|
||||
DereferenceNode dereferenceNode => EmitDereference(dereferenceNode),
|
||||
Float32LiteralNode float32LiteralNode => EmitFloat32Literal(float32LiteralNode),
|
||||
Float64LiteralNode float64LiteralNode => EmitFloat64Literal(float64LiteralNode),
|
||||
FloatToIntBuiltinNode floatToIntBuiltinNode => EmitFloatToIntBuiltin(floatToIntBuiltinNode),
|
||||
FuncCallNode funcCallNode => EmitFuncCall(funcCallNode),
|
||||
FuncIdentifierNode funcIdentifierNode => EmitFuncIdentifier(funcIdentifierNode),
|
||||
FuncIdentifierNode funcIdentifierNode => FuncName(funcIdentifierNode.Module, funcIdentifierNode.Name, funcIdentifierNode.ExternSymbol),
|
||||
IntLiteralNode intLiteralNode => EmitIntLiteral(intLiteralNode),
|
||||
AddressOfNode addressOfNode => EmitAddressOf(addressOfNode),
|
||||
LValueIdentifierNode lValueIdentifierNode => EmitLValueIdentifier(lValueIdentifierNode),
|
||||
RValueIdentifierNode rValueIdentifierNode => EmitRValueIdentifier(rValueIdentifierNode),
|
||||
SizeBuiltinNode sizeBuiltinNode => EmitSizeBuiltin(sizeBuiltinNode),
|
||||
SizeBuiltinNode sizeBuiltinNode => $"sizeof({CType.Create(sizeBuiltinNode.TargetType)})",
|
||||
SliceIndexAccessNode sliceIndexAccessNode => EmitSliceArrayIndexAccess(sliceIndexAccessNode),
|
||||
StringLiteralNode stringLiteralNode => EmitStringLiteral(stringLiteralNode),
|
||||
StructFieldAccessNode structFieldAccessNode => EmitStructFieldAccess(structFieldAccessNode),
|
||||
StructInitializerNode structInitializerNode => EmitStructInitializer(structInitializerNode),
|
||||
UIntLiteralNode uIntLiteralNode => EmitUIntLiteral(uIntLiteralNode),
|
||||
UnaryExpressionNode unaryExpressionNode => EmitUnaryExpression(unaryExpressionNode),
|
||||
VariableIdentifierNode variableIdentifierNode => variableIdentifierNode.Name,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(expressionNode))
|
||||
};
|
||||
|
||||
if (expressionNode is ConstArrayInitializerNode)
|
||||
{
|
||||
return expr;
|
||||
}
|
||||
|
||||
return $"({expr})";
|
||||
}
|
||||
|
||||
@@ -309,10 +299,9 @@ public class Generator
|
||||
|
||||
private string EmitArrayInitializer(ArrayInitializerNode arrayInitializerNode)
|
||||
{
|
||||
var type = (NubArrayType)arrayInitializerNode.Type;
|
||||
var capacity = EmitExpression(arrayInitializerNode.Capacity);
|
||||
var tmp = NewTmp();
|
||||
_writer.WriteLine($"{CType.Create(type.ElementType)} {tmp}[{capacity}];");
|
||||
_writer.WriteLine($"{CType.Create(arrayInitializerNode.ElementType)} {tmp}[{capacity}];");
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@@ -347,30 +336,12 @@ public class Generator
|
||||
return $"{left} {op} {right}";
|
||||
}
|
||||
|
||||
private string EmitBoolLiteral(BoolLiteralNode boolLiteralNode)
|
||||
private string EmitConvertCStringToString(ConvertCStringToStringNode convertCStringToStringNode)
|
||||
{
|
||||
return boolLiteralNode.Value ? "true" : "false";
|
||||
var value = EmitExpression(convertCStringToStringNode.Value);
|
||||
return $"(string){{.length = strlen({value}), .data = {value}}}";
|
||||
}
|
||||
|
||||
private string EmitConstArrayIndexAccess(ConstArrayIndexAccessNode constArrayIndexAccessNode)
|
||||
{
|
||||
var array = EmitExpression(constArrayIndexAccessNode.Target);
|
||||
var index = EmitExpression(constArrayIndexAccessNode.Index);
|
||||
// todo(nub31): We can emit bounds checking here
|
||||
return $"{array}[{index}]";
|
||||
}
|
||||
|
||||
private string EmitConstArrayInitializer(ConstArrayInitializerNode constArrayInitializerNode)
|
||||
{
|
||||
return "{0}";
|
||||
}
|
||||
|
||||
// private string EmitConvertConstArrayToArray(ConvertConstArrayToArrayNode convertConstArrayToArrayNode)
|
||||
// {
|
||||
// var value = EmitExpression(convertConstArrayToArrayNode.Value);
|
||||
// return $"({CType.Create(convertConstArrayToArrayNode.Type)}){value}";
|
||||
// }
|
||||
|
||||
private string EmitConvertFloat(ConvertFloatNode convertFloatNode)
|
||||
{
|
||||
var value = EmitExpression(convertFloatNode.Value);
|
||||
@@ -387,24 +358,21 @@ public class Generator
|
||||
private string EmitConvertInt(ConvertIntNode convertIntNode)
|
||||
{
|
||||
var value = EmitExpression(convertIntNode.Value);
|
||||
var targetType = (convertIntNode.TargetType.Signed, convertIntNode.TargetType.Width) switch
|
||||
var targetType = convertIntNode.TargetType.Width switch
|
||||
{
|
||||
(false, 8) => "u8",
|
||||
(false, 16) => "u16",
|
||||
(false, 32) => "u32",
|
||||
(false, 64) => "u64",
|
||||
(true, 8) => "i8",
|
||||
(true, 16) => "i16",
|
||||
(true, 32) => "i32",
|
||||
(true, 64) => "i64",
|
||||
8 => convertIntNode.TargetType.Signed ? "int8_t" : "uint8_t",
|
||||
16 => convertIntNode.TargetType.Signed ? "int16_t" : "uint16_t",
|
||||
32 => convertIntNode.TargetType.Signed ? "int32_t" : "uint32_t",
|
||||
64 => convertIntNode.TargetType.Signed ? "int64_t" : "uint64_t",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
return $"({targetType}){value}";
|
||||
}
|
||||
|
||||
private string EmitCStringLiteral(CStringLiteralNode cStringLiteralNode)
|
||||
private string EmitConvertStringToCString(ConvertStringToCStringNode convertStringToCStringNode)
|
||||
{
|
||||
return $"\"{cStringLiteralNode.Value}\"";
|
||||
var value = EmitExpression(convertStringToCStringNode.Value);
|
||||
return $"(char*){value}.data";
|
||||
}
|
||||
|
||||
private string EmitDereference(DereferenceNode dereferenceNode)
|
||||
@@ -438,16 +406,12 @@ public class Generator
|
||||
private string EmitFloatToIntBuiltin(FloatToIntBuiltinNode floatToIntBuiltinNode)
|
||||
{
|
||||
var value = EmitExpression(floatToIntBuiltinNode.Value);
|
||||
var targetType = (floatToIntBuiltinNode.TargetType.Signed, floatToIntBuiltinNode.TargetType.Width) switch
|
||||
var targetType = floatToIntBuiltinNode.TargetType.Width switch
|
||||
{
|
||||
(false, 8) => "u8",
|
||||
(false, 16) => "u16",
|
||||
(false, 32) => "u32",
|
||||
(false, 64) => "u64",
|
||||
(true, 8) => "i8",
|
||||
(true, 16) => "i16",
|
||||
(true, 32) => "i32",
|
||||
(true, 64) => "i64",
|
||||
8 => floatToIntBuiltinNode.TargetType.Signed ? "int8_t" : "uint8_t",
|
||||
16 => floatToIntBuiltinNode.TargetType.Signed ? "int16_t" : "uint16_t",
|
||||
32 => floatToIntBuiltinNode.TargetType.Signed ? "int32_t" : "uint32_t",
|
||||
64 => floatToIntBuiltinNode.TargetType.Signed ? "int64_t" : "uint64_t",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
return $"({targetType}){value}";
|
||||
@@ -460,11 +424,6 @@ public class Generator
|
||||
return $"{name}({string.Join(", ", parameterNames)})";
|
||||
}
|
||||
|
||||
private string EmitFuncIdentifier(FuncIdentifierNode funcIdentifierNode)
|
||||
{
|
||||
return FuncName(funcIdentifierNode.Module, funcIdentifierNode.Name, funcIdentifierNode.ExternSymbol);
|
||||
}
|
||||
|
||||
private string EmitIntLiteral(IntLiteralNode intLiteralNode)
|
||||
{
|
||||
var type = (NubIntType)intLiteralNode.Type;
|
||||
@@ -482,32 +441,18 @@ public class Generator
|
||||
return $"&{value}";
|
||||
}
|
||||
|
||||
private string EmitLValueIdentifier(LValueIdentifierNode lValueIdentifierNode)
|
||||
{
|
||||
return lValueIdentifierNode.Name;
|
||||
}
|
||||
|
||||
private string EmitRValueIdentifier(RValueIdentifierNode rValueIdentifierNode)
|
||||
{
|
||||
return rValueIdentifierNode.Name;
|
||||
}
|
||||
|
||||
private string EmitSizeBuiltin(SizeBuiltinNode sizeBuiltinNode)
|
||||
{
|
||||
return $"sizeof({CType.Create(sizeBuiltinNode.TargetType)})";
|
||||
}
|
||||
|
||||
private string EmitSliceArrayIndexAccess(SliceIndexAccessNode sliceIndexAccessNode)
|
||||
{
|
||||
var value = EmitExpression(sliceIndexAccessNode.Target);
|
||||
var index = EmitExpression(sliceIndexAccessNode.Index);
|
||||
// todo(nub31): We can emit bounds checking here
|
||||
return $"{value}.data[{index}]";
|
||||
return $"(({CType.Create(sliceIndexAccessNode.Target.Type)}){value}.data)[{index}]";
|
||||
}
|
||||
|
||||
private string EmitStringLiteral(StringLiteralNode stringLiteralNode)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var length = Encoding.UTF8.GetByteCount(stringLiteralNode.Value);
|
||||
return $"(string){{.length = {length}, .data = \"{stringLiteralNode.Value}\"}}";
|
||||
}
|
||||
|
||||
private string EmitStructFieldAccess(StructFieldAccessNode structFieldAccessNode)
|
||||
|
||||
@@ -531,21 +531,12 @@ public sealed class Parser
|
||||
}
|
||||
|
||||
private ExpressionSyntax ParseArrayInitializer(int startIndex)
|
||||
{
|
||||
if (TryExpectIntLiteral(out var intLiteral))
|
||||
{
|
||||
ExpectSymbol(Symbol.CloseBracket);
|
||||
var type = ParseType();
|
||||
return new ConstArrayInitializerSyntax(GetTokens(startIndex), Convert.ToInt64(intLiteral.Value, intLiteral.Base), type);
|
||||
}
|
||||
else
|
||||
{
|
||||
var capacity = ParseExpression();
|
||||
ExpectSymbol(Symbol.CloseBracket);
|
||||
var type = ParseType();
|
||||
return new ArrayInitializerSyntax(GetTokens(startIndex), capacity, type);
|
||||
}
|
||||
}
|
||||
|
||||
private StructInitializerSyntax ParseStructInitializer(int startIndex)
|
||||
{
|
||||
|
||||
@@ -88,8 +88,6 @@ public record ModuleIdentifierSyntax(List<Token> Tokens, string Module, string N
|
||||
|
||||
public record ArrayInitializerSyntax(List<Token> Tokens, ExpressionSyntax Capacity, TypeSyntax ElementType) : ExpressionSyntax(Tokens);
|
||||
|
||||
public record ConstArrayInitializerSyntax(List<Token> Tokens, long Capacity, TypeSyntax ElementType) : ExpressionSyntax(Tokens);
|
||||
|
||||
public record ArrayIndexAccessSyntax(List<Token> Tokens, ExpressionSyntax Target, ExpressionSyntax Index) : ExpressionSyntax(Tokens);
|
||||
|
||||
public record AddressOfSyntax(List<Token> Tokens, ExpressionSyntax Target) : ExpressionSyntax(Tokens);
|
||||
|
||||
@@ -4,7 +4,6 @@ extern "puts" func puts(text: cstring)
|
||||
|
||||
extern "main" func main(argc: i64, argv: [?]cstring): i64
|
||||
{
|
||||
let x = [10]i32
|
||||
x[0] = 23
|
||||
return 0
|
||||
let x = [23]i32
|
||||
return x[0]
|
||||
}
|
||||
@@ -2,9 +2,9 @@ module "main"
|
||||
|
||||
extern "puts" func puts(text: cstring)
|
||||
|
||||
extern "main" func main(args: []cstring): i64
|
||||
func main(argc: i32, argv: [?]cstring): i32
|
||||
{
|
||||
defer puts("Goodybye World")
|
||||
puts("Hello World")
|
||||
defer puts("Bye cruel world!")
|
||||
puts("Hello world!")
|
||||
return 0
|
||||
}
|
||||
Reference in New Issue
Block a user