This commit is contained in:
nub31
2025-05-28 14:15:16 +02:00
parent 3d095ec648
commit a098065136
7 changed files with 93 additions and 53 deletions

View File

@@ -1,24 +1,30 @@
namespace main
struct Human {
}
/// # Documentation
/// ## Documentation subtitle
export func main(args: []string) {
export func main(args: []^string) {
let i: i64
c::printf("%d\n", args.count)
while i < args.count {
c::printf("%s\n", args[i])
i === 1
i += 1
}
let arr = new [10]i64
let human = alloc Human {}
let arr = [10]^i64
i = 0
while i < arr.count {
while i < arr.count + 1 {
c::printf("%d\n", arr[i])
i === 1
i += 1
}
c::printf("success\n", "")
}

View File

@@ -7,6 +7,8 @@ namespace Nub.Lang.Backend;
public class Generator
{
private const string OutOfBoundsMessage = "Index is out of bounds\n";
private List<SourceFile> _sourceFiles = [];
private StringBuilder _builder = new();
private Dictionary<string, Variable> _variables = [];
@@ -68,6 +70,8 @@ public class Generator
_builder.AppendLine();
}
_builder.AppendLine($"data $oob_message = {{ b \"{OutOfBoundsMessage}\" }}");
for (var i = 0; i < _strings.Count; i++)
{
var str = _strings[i];
@@ -579,14 +583,38 @@ public class Generator
var arrayBaseType = ((NubArrayType)arrayIndex.Expression.Type).BaseType;
var countName = GenVarName();
_builder.AppendLine($" %{countName} =l loadl {array}");
var isNegativeName = GenVarName();
_builder.AppendLine($" %{isNegativeName} =w csltl {index}, 0");
var isOobName = GenVarName();
_builder.AppendLine($" %{isOobName} =w csgel {index}, %{countName}");
var anyOobName = GenVarName();
_builder.AppendLine($" %{anyOobName} =w or %{isNegativeName}, %{isOobName}");
var oobLabel = GenLabelName();
var notOobLabel = GenLabelName();
_builder.AppendLine($" jnz %{anyOobName}, @{oobLabel}, @{notOobLabel}");
_builder.AppendLine($"@{oobLabel}");
_builder.AppendLine($" call $nub_panic(l $oob_message, l {OutOfBoundsMessage.Length})");
_builder.AppendLine($"@{notOobLabel}");
// Calculate element address
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}");
_builder.AppendLine($" %{resultPointerName} =l add %{firstItemPointerName}, %{offsetPointerName}");
// Load the value
var outputName = GenVarName();
_builder.AppendLine($" %{outputName} =l load{SQT(arrayBaseType)} %{resultPointerName}");
_builder.AppendLine($" %{outputName} ={SQT(arrayBaseType)} load{SQT(arrayBaseType)} %{resultPointerName}");
return $"%{outputName}";
}

View File

@@ -15,7 +15,7 @@ public class Lexer
["break"] = Symbol.Break,
["continue"] = Symbol.Continue,
["return"] = Symbol.Return,
["new"] = Symbol.New,
["alloc"] = Symbol.Alloc,
["struct"] = Symbol.Struct,
["let"] = Symbol.Let,
};

View File

@@ -38,11 +38,11 @@ public enum Symbol
Minus,
Star,
ForwardSlash,
New,
Struct,
Caret,
Ampersand,
DoubleColon,
Namespace,
Let
Let,
Alloc
}

View File

@@ -507,18 +507,33 @@ public class Parser
expr = new CastNode(GetTokensForNode(startIndex), type, expressionToCast);
break;
}
case Symbol.New:
case Symbol.Ampersand:
{
var next = Peek();
if (next.Value is SymbolToken { Symbol: Symbol.OpenBracket })
var expression = ParsePrimaryExpression();
expr = new AddressOfNode(GetTokensForNode(startIndex), expression);
break;
}
case Symbol.Minus:
{
var expression = ParsePrimaryExpression();
expr = new UnaryExpressionNode(GetTokensForNode(startIndex), UnaryExpressionOperator.Negate, expression);
break;
}
case Symbol.Bang:
{
var expression = ParsePrimaryExpression();
expr = new UnaryExpressionNode(GetTokensForNode(startIndex), UnaryExpressionOperator.Invert, expression);
break;
}
case Symbol.OpenBracket:
{
Next();
var size = ParseExpression();
ExpectSymbol(Symbol.CloseBracket);
var type = ParseType();
expr = new ArrayInitializerNode(GetTokensForNode(startIndex), size, type);
break;
}
else
case Symbol.Alloc:
{
var type = ParseType();
Dictionary<string, ExpressionNode> initializers = [];
@@ -540,26 +555,6 @@ public class Parser
}
expr = new StructInitializerNode(GetTokensForNode(startIndex), structType, initializers);
}
break;
}
case Symbol.Ampersand:
{
var expression = ParsePrimaryExpression();
expr = new AddressOfNode(GetTokensForNode(startIndex), expression);
break;
}
case Symbol.Minus:
{
var expression = ParsePrimaryExpression();
expr = new UnaryExpressionNode(GetTokensForNode(startIndex), UnaryExpressionOperator.Negate, expression);
break;
}
case Symbol.Bang:
{
var expression = ParsePrimaryExpression();
expr = new UnaryExpressionNode(GetTokensForNode(startIndex), UnaryExpressionOperator.Invert, expression);
break;
}
default:

View File

@@ -28,6 +28,17 @@ nub_strcmp:
mov rax, 1
ret
global nub_panic
nub_panic:
mov rdx, rsi
mov rsi, rdi
mov rax, 1
mov rdi, 2
syscall
mov rax, 60
mov rdi, 101
syscall
; TODO: This is ai-generated. Should be re-implemented in the future
global nub_memset
nub_memset:

View File

@@ -60,7 +60,7 @@
},
{
"name": "keyword.other.nub",
"match": "\\b(namespace|func|struct|new)\\b"
"match": "\\b(namespace|func|struct|alloc)\\b"
}
]
},