...
This commit is contained in:
@@ -1,24 +1,30 @@
|
|||||||
namespace main
|
namespace main
|
||||||
|
|
||||||
|
struct Human {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/// # Documentation
|
/// # Documentation
|
||||||
/// ## Documentation subtitle
|
/// ## Documentation subtitle
|
||||||
export func main(args: []string) {
|
export func main(args: []^string) {
|
||||||
let i: i64
|
let i: i64
|
||||||
|
|
||||||
c::printf("%d\n", args.count)
|
c::printf("%d\n", args.count)
|
||||||
|
|
||||||
while i < args.count {
|
while i < args.count {
|
||||||
c::printf("%s\n", args[i])
|
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
|
i = 0
|
||||||
|
|
||||||
while i < arr.count {
|
while i < arr.count + 1 {
|
||||||
c::printf("%d\n", arr[i])
|
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
|
public class Generator
|
||||||
{
|
{
|
||||||
|
private const string OutOfBoundsMessage = "Index is out of bounds\n";
|
||||||
|
|
||||||
private List<SourceFile> _sourceFiles = [];
|
private List<SourceFile> _sourceFiles = [];
|
||||||
private StringBuilder _builder = new();
|
private StringBuilder _builder = new();
|
||||||
private Dictionary<string, Variable> _variables = [];
|
private Dictionary<string, Variable> _variables = [];
|
||||||
@@ -68,12 +70,14 @@ public class Generator
|
|||||||
_builder.AppendLine();
|
_builder.AppendLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_builder.AppendLine($"data $oob_message = {{ b \"{OutOfBoundsMessage}\" }}");
|
||||||
|
|
||||||
for (var i = 0; i < _strings.Count; i++)
|
for (var i = 0; i < _strings.Count; i++)
|
||||||
{
|
{
|
||||||
var str = _strings[i];
|
var str = _strings[i];
|
||||||
_builder.AppendLine($"data $str{i + 1} = {{ b \"{str}\", b 0 }}");
|
_builder.AppendLine($"data $str{i + 1} = {{ b \"{str}\", b 0 }}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return _builder.ToString();
|
return _builder.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -578,15 +582,39 @@ public class Generator
|
|||||||
var index = GenerateExpression(arrayIndex.Index);
|
var index = GenerateExpression(arrayIndex.Index);
|
||||||
|
|
||||||
var arrayBaseType = ((NubArrayType)arrayIndex.Expression.Type).BaseType;
|
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();
|
var firstItemPointerName = GenVarName();
|
||||||
_builder.AppendLine($" %{firstItemPointerName} =l add {array}, 8");
|
_builder.AppendLine($" %{firstItemPointerName} =l add {array}, 8");
|
||||||
var offsetPointerName = GenVarName();
|
var offsetPointerName = GenVarName();
|
||||||
_builder.AppendLine($" %{offsetPointerName} =l mul {index}, {QbeTypeSize(arrayBaseType)}");
|
_builder.AppendLine($" %{offsetPointerName} =l mul {index}, {QbeTypeSize(arrayBaseType)}");
|
||||||
var resultPointerName = GenVarName();
|
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();
|
var outputName = GenVarName();
|
||||||
_builder.AppendLine($" %{outputName} =l load{SQT(arrayBaseType)} %{resultPointerName}");
|
_builder.AppendLine($" %{outputName} ={SQT(arrayBaseType)} load{SQT(arrayBaseType)} %{resultPointerName}");
|
||||||
return $"%{outputName}";
|
return $"%{outputName}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public class Lexer
|
|||||||
["break"] = Symbol.Break,
|
["break"] = Symbol.Break,
|
||||||
["continue"] = Symbol.Continue,
|
["continue"] = Symbol.Continue,
|
||||||
["return"] = Symbol.Return,
|
["return"] = Symbol.Return,
|
||||||
["new"] = Symbol.New,
|
["alloc"] = Symbol.Alloc,
|
||||||
["struct"] = Symbol.Struct,
|
["struct"] = Symbol.Struct,
|
||||||
["let"] = Symbol.Let,
|
["let"] = Symbol.Let,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -38,11 +38,11 @@ public enum Symbol
|
|||||||
Minus,
|
Minus,
|
||||||
Star,
|
Star,
|
||||||
ForwardSlash,
|
ForwardSlash,
|
||||||
New,
|
|
||||||
Struct,
|
Struct,
|
||||||
Caret,
|
Caret,
|
||||||
Ampersand,
|
Ampersand,
|
||||||
DoubleColon,
|
DoubleColon,
|
||||||
Namespace,
|
Namespace,
|
||||||
Let
|
Let,
|
||||||
|
Alloc
|
||||||
}
|
}
|
||||||
@@ -507,43 +507,6 @@ public class Parser
|
|||||||
expr = new CastNode(GetTokensForNode(startIndex), type, expressionToCast);
|
expr = new CastNode(GetTokensForNode(startIndex), type, expressionToCast);
|
||||||
break;
|
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:
|
case Symbol.Ampersand:
|
||||||
{
|
{
|
||||||
var expression = ParsePrimaryExpression();
|
var expression = ParsePrimaryExpression();
|
||||||
@@ -562,6 +525,38 @@ public class Parser
|
|||||||
expr = new UnaryExpressionNode(GetTokensForNode(startIndex), UnaryExpressionOperator.Invert, expression);
|
expr = new UnaryExpressionNode(GetTokensForNode(startIndex), UnaryExpressionOperator.Invert, expression);
|
||||||
break;
|
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:
|
default:
|
||||||
{
|
{
|
||||||
throw new ParseException(Diagnostic
|
throw new ParseException(Diagnostic
|
||||||
|
|||||||
@@ -28,6 +28,17 @@ nub_strcmp:
|
|||||||
mov rax, 1
|
mov rax, 1
|
||||||
ret
|
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
|
; TODO: This is ai-generated. Should be re-implemented in the future
|
||||||
global nub_memset
|
global nub_memset
|
||||||
nub_memset:
|
nub_memset:
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "keyword.other.nub",
|
"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