...
This commit is contained in:
@@ -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", "")
|
||||
}
|
||||
@@ -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,12 +70,14 @@ public class Generator
|
||||
_builder.AppendLine();
|
||||
}
|
||||
|
||||
_builder.AppendLine($"data $oob_message = {{ b \"{OutOfBoundsMessage}\" }}");
|
||||
|
||||
for (var i = 0; i < _strings.Count; i++)
|
||||
{
|
||||
var str = _strings[i];
|
||||
_builder.AppendLine($"data $str{i + 1} = {{ b \"{str}\", b 0 }}");
|
||||
}
|
||||
|
||||
|
||||
return _builder.ToString();
|
||||
}
|
||||
|
||||
@@ -578,15 +582,39 @@ public class Generator
|
||||
var index = GenerateExpression(arrayIndex.Index);
|
||||
|
||||
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}";
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -38,11 +38,11 @@ public enum Symbol
|
||||
Minus,
|
||||
Star,
|
||||
ForwardSlash,
|
||||
New,
|
||||
Struct,
|
||||
Caret,
|
||||
Ampersand,
|
||||
DoubleColon,
|
||||
Namespace,
|
||||
Let
|
||||
Let,
|
||||
Alloc
|
||||
}
|
||||
@@ -507,43 +507,6 @@ public class Parser
|
||||
expr = new CastNode(GetTokensForNode(startIndex), type, expressionToCast);
|
||||
break;
|
||||
}
|
||||
case Symbol.New:
|
||||
{
|
||||
var next = Peek();
|
||||
if (next.Value is SymbolToken { Symbol: Symbol.OpenBracket })
|
||||
{
|
||||
Next();
|
||||
var size = ParseExpression();
|
||||
ExpectSymbol(Symbol.CloseBracket);
|
||||
var type = ParseType();
|
||||
expr = new ArrayInitializerNode(GetTokensForNode(startIndex), size, type);
|
||||
}
|
||||
else
|
||||
{
|
||||
var type = ParseType();
|
||||
Dictionary<string, ExpressionNode> initializers = [];
|
||||
ExpectSymbol(Symbol.OpenBrace);
|
||||
while (!TryExpectSymbol(Symbol.CloseBrace))
|
||||
{
|
||||
var name = ExpectIdentifier().Value;
|
||||
ExpectSymbol(Symbol.Assign);
|
||||
var value = ParseExpression();
|
||||
initializers.Add(name, value);
|
||||
}
|
||||
|
||||
if (type is not NubStructType structType)
|
||||
{
|
||||
throw new ParseException(Diagnostic
|
||||
.Error($"Cannot use new keyword on type {type}")
|
||||
.At(symbolToken)
|
||||
.Build());
|
||||
}
|
||||
|
||||
expr = new StructInitializerNode(GetTokensForNode(startIndex), structType, initializers);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case Symbol.Ampersand:
|
||||
{
|
||||
var expression = ParsePrimaryExpression();
|
||||
@@ -562,6 +525,38 @@ public class Parser
|
||||
expr = new UnaryExpressionNode(GetTokensForNode(startIndex), UnaryExpressionOperator.Invert, expression);
|
||||
break;
|
||||
}
|
||||
case Symbol.OpenBracket:
|
||||
{
|
||||
var size = ParseExpression();
|
||||
ExpectSymbol(Symbol.CloseBracket);
|
||||
var type = ParseType();
|
||||
expr = new ArrayInitializerNode(GetTokensForNode(startIndex), size, type);
|
||||
break;
|
||||
}
|
||||
case Symbol.Alloc:
|
||||
{
|
||||
var type = ParseType();
|
||||
Dictionary<string, ExpressionNode> initializers = [];
|
||||
ExpectSymbol(Symbol.OpenBrace);
|
||||
while (!TryExpectSymbol(Symbol.CloseBrace))
|
||||
{
|
||||
var name = ExpectIdentifier().Value;
|
||||
ExpectSymbol(Symbol.Assign);
|
||||
var value = ParseExpression();
|
||||
initializers.Add(name, value);
|
||||
}
|
||||
|
||||
if (type is not NubStructType structType)
|
||||
{
|
||||
throw new ParseException(Diagnostic
|
||||
.Error($"Cannot use new keyword on type {type}")
|
||||
.At(symbolToken)
|
||||
.Build());
|
||||
}
|
||||
|
||||
expr = new StructInitializerNode(GetTokensForNode(startIndex), structType, initializers);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new ParseException(Diagnostic
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
},
|
||||
{
|
||||
"name": "keyword.other.nub",
|
||||
"match": "\\b(namespace|func|struct|new)\\b"
|
||||
"match": "\\b(namespace|func|struct|alloc)\\b"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -256,4 +256,4 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user