Function pointers are working
This commit is contained in:
@@ -337,4 +337,4 @@ namespace sys
|
||||
// let rseq: i64 = 334
|
||||
// let pkey_mprotect: i64 = 335
|
||||
|
||||
extern func call(num: i64, ...args: any) calls core_syscall
|
||||
// extern func call(num: i64, ...args: any) calls core_syscall
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
namespace c
|
||||
|
||||
extern func printf(fmt: ^u8, ...args: any): void
|
||||
extern func getchar(): i32
|
||||
extern func puts(fmt: ^u8)
|
||||
// extern func printf(fmt: ^u8, ...args: any): void
|
||||
// extern func getchar(): i32
|
||||
extern func puts(fmt: []u8)
|
||||
|
||||
extern func malloc(size: i64): ^void
|
||||
extern func calloc(num: i64, size: i64): ^void
|
||||
extern func realloc(ptr: ^void, size: i64): ^void
|
||||
extern func free(ptr: ^void)
|
||||
// extern func malloc(size: i64): ^void
|
||||
// extern func calloc(num: i64, size: i64): ^void
|
||||
// extern func realloc(ptr: ^void, size: i64): ^void
|
||||
// extern func free(ptr: ^void)
|
||||
|
||||
extern func sin(x: f64): f64
|
||||
extern func cos(x: f64): f64
|
||||
extern func tan(x: f64): f64
|
||||
extern func sqrt(x: f64): f64
|
||||
extern func pow(x: f64, y: f64): f64
|
||||
extern func abs(x: i32): i32
|
||||
// extern func sin(x: f64): f64
|
||||
// extern func cos(x: f64): f64
|
||||
// extern func tan(x: f64): f64
|
||||
// extern func sqrt(x: f64): f64
|
||||
// extern func pow(x: f64, y: f64): f64
|
||||
// extern func abs(x: i32): i32
|
||||
|
||||
extern func time(t: ^i64): i64
|
||||
extern func clock(): i64
|
||||
extern func sleep(seconds: u32): i32
|
||||
// extern func time(t: ^i64): i64
|
||||
// extern func clock(): i64
|
||||
// extern func sleep(seconds: u32): i32
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
namespace main
|
||||
|
||||
struct Human {
|
||||
age: ^u64
|
||||
age: u64
|
||||
print_age: func() = () => {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export func main(args: []^string): i64 {
|
||||
let age: u64 = 23
|
||||
|
||||
let me = alloc Human {
|
||||
age = &age
|
||||
age = 23
|
||||
}
|
||||
|
||||
me.age^ = 24.5
|
||||
me.print_age()
|
||||
|
||||
test(me.age^)
|
||||
print_age()
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func test(me: u64) {
|
||||
c::printf("%d\n", me)
|
||||
func print_age() {
|
||||
c::puts("TEST")
|
||||
}
|
||||
@@ -107,6 +107,7 @@ public class QBEGenerator
|
||||
},
|
||||
NubStructType => "l",
|
||||
NubFixedArrayType => "l",
|
||||
NubFuncType => "l",
|
||||
_ => throw new NotSupportedException($"'{type}' type cannot be used in store instructions")
|
||||
}}";
|
||||
}
|
||||
@@ -134,6 +135,7 @@ public class QBEGenerator
|
||||
},
|
||||
NubStructType => "l",
|
||||
NubFixedArrayType => "l",
|
||||
NubFuncType => "l",
|
||||
_ => throw new NotSupportedException($"'{type}' type cannot be used in load instructions")
|
||||
}}";
|
||||
}
|
||||
@@ -161,6 +163,7 @@ public class QBEGenerator
|
||||
},
|
||||
NubStructType => "l",
|
||||
NubFixedArrayType => "l",
|
||||
NubFuncType => "l",
|
||||
_ => throw new NotSupportedException($"'{type}' type cannot be used in variables")
|
||||
}}";
|
||||
}
|
||||
@@ -195,17 +198,16 @@ public class QBEGenerator
|
||||
case NubStructType nubStructType:
|
||||
{
|
||||
var definition = LookupStructDefinition(nubStructType.Namespace, nubStructType.Name);
|
||||
// Struct alignment is the maximum alignment of its fields
|
||||
return definition.Fields.Max(f => AlignmentOf(f.Type));
|
||||
}
|
||||
case NubPointerType:
|
||||
case NubArrayType:
|
||||
case NubFuncType:
|
||||
{
|
||||
return 8; // Pointer alignment (assuming 64-bit)
|
||||
return 8;
|
||||
}
|
||||
case NubFixedArrayType nubFixedArrayType:
|
||||
{
|
||||
// Array alignment is same as element alignment
|
||||
return AlignmentOf(nubFixedArrayType.ElementType);
|
||||
}
|
||||
default:
|
||||
@@ -261,27 +263,25 @@ public class QBEGenerator
|
||||
int fieldAlignment = AlignmentOf(field.Type);
|
||||
maxAlignment = Math.Max(maxAlignment, fieldAlignment);
|
||||
|
||||
// Align current position for this field
|
||||
size = AlignTo(size, fieldAlignment);
|
||||
|
||||
// Add field size
|
||||
size += SizeOf(field.Type);
|
||||
}
|
||||
|
||||
// Align final size to struct's alignment for array compatibility
|
||||
size = AlignTo(size, maxAlignment);
|
||||
|
||||
return size;
|
||||
}
|
||||
case NubPointerType:
|
||||
case NubArrayType:
|
||||
case NubFuncType:
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
case NubFixedArrayType nubFixedArrayType:
|
||||
{
|
||||
int elementSize = SizeOf(nubFixedArrayType.ElementType);
|
||||
return elementSize * nubFixedArrayType.Capacity + 8; // +8 for length/capacity info
|
||||
return elementSize * nubFixedArrayType.Capacity + 8;
|
||||
}
|
||||
default:
|
||||
{
|
||||
@@ -299,6 +299,7 @@ public class QBEGenerator
|
||||
NubPrimitiveType => false,
|
||||
NubStructType => true,
|
||||
NubFixedArrayType => true,
|
||||
NubFuncType => false,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(type))
|
||||
};
|
||||
}
|
||||
@@ -336,6 +337,7 @@ public class QBEGenerator
|
||||
},
|
||||
NubStructType structType => $":{structType.Namespace}_{structType.Name}",
|
||||
NubFixedArrayType => "l",
|
||||
NubFuncType => "l",
|
||||
_ => throw new NotSupportedException($"'{node.ReturnType}' type cannot be used as a function return type")
|
||||
});
|
||||
_builder.Append(' ');
|
||||
@@ -343,7 +345,7 @@ public class QBEGenerator
|
||||
|
||||
_builder.Append(_funcNames[node]);
|
||||
|
||||
var parameterStrings = node.Parameters.Select(parameter => parameter.Variadic ? "..." : $"{parameter.Type switch
|
||||
var parameterStrings = node.Parameters.Select(parameter => $"{parameter.Type switch
|
||||
{
|
||||
NubArrayType => "l",
|
||||
NubPointerType => "l",
|
||||
@@ -364,6 +366,7 @@ public class QBEGenerator
|
||||
},
|
||||
NubStructType structType => $":{structType.Namespace}_{structType.Name}",
|
||||
NubFixedArrayType => "l",
|
||||
NubFuncType => "l",
|
||||
_ => throw new NotSupportedException($"'{parameter.Type}' type cannot be used as a function parameter type")
|
||||
}} %{parameter.Name}");
|
||||
|
||||
@@ -439,6 +442,7 @@ public class QBEGenerator
|
||||
},
|
||||
NubStructType structType => $":{structType.Namespace}_{structType.Name}",
|
||||
NubFixedArrayType fixedArrayType => $"b {SizeOf(fixedArrayType)}",
|
||||
NubFuncType => "l",
|
||||
_ => throw new NotSupportedException($"'{structDefinitionField.Type}' type cannot be used in structs")
|
||||
};
|
||||
_builder.Append(fieldQbeType + ", ");
|
||||
@@ -619,7 +623,7 @@ public class QBEGenerator
|
||||
private void GenerateVariableAssignment(VariableAssignmentNode variableAssignment)
|
||||
{
|
||||
var value = GenerateExpression(variableAssignment.Value);
|
||||
var pointer = _variables[variableAssignment.Identifier.Identifier];
|
||||
var pointer = _variables[variableAssignment.Identifier.Name];
|
||||
GenerateCopy(variableAssignment.Value.Type, value, pointer);
|
||||
}
|
||||
|
||||
@@ -795,7 +799,7 @@ public class QBEGenerator
|
||||
case DereferenceNode dereference:
|
||||
return GenerateExpression(dereference.Expression);
|
||||
case IdentifierNode identifier:
|
||||
return _variables[identifier.Identifier];
|
||||
return _variables[identifier.Name];
|
||||
case MemberAccessNode memberAccess:
|
||||
return GenerateMemberAccessPointer(memberAccess);
|
||||
default:
|
||||
@@ -1031,7 +1035,14 @@ public class QBEGenerator
|
||||
|
||||
private string GenerateIdentifier(IdentifierNode identifier)
|
||||
{
|
||||
return _variables[identifier.Identifier];
|
||||
if (_variables.TryGetValue(identifier.Name, out var value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _funcNames[LookupFuncSignature(identifier.Namespace, identifier.Name)];
|
||||
}
|
||||
}
|
||||
|
||||
private string GenerateLiteral(LiteralNode literal)
|
||||
@@ -1223,21 +1234,12 @@ public class QBEGenerator
|
||||
|
||||
private string GenerateFuncCall(FuncCallNode funcCall)
|
||||
{
|
||||
var funcDefinition = LookupFuncSignature(funcCall.Namespace, funcCall.Name);
|
||||
if (funcDefinition == null)
|
||||
{
|
||||
throw new Exception($"Unknown function {funcCall}");
|
||||
}
|
||||
|
||||
var funcType = (NubFuncType)funcCall.Expression.Type;
|
||||
|
||||
var parameterStrings = new List<string>();
|
||||
|
||||
for (var i = 0; i < funcCall.Parameters.Count; i++)
|
||||
{
|
||||
if (i < funcDefinition.Parameters.Count && funcDefinition.Parameters[i].Variadic)
|
||||
{
|
||||
parameterStrings.Add("...");
|
||||
}
|
||||
|
||||
var parameter = funcCall.Parameters[i];
|
||||
var result = GenerateExpression(parameter);
|
||||
|
||||
@@ -1262,22 +1264,23 @@ public class QBEGenerator
|
||||
},
|
||||
NubStructType structType => $":{structType.Namespace}_{structType.Name}",
|
||||
NubFixedArrayType => "l",
|
||||
NubFuncType => "l",
|
||||
_ => throw new NotSupportedException($"'{parameter.Type}' type cannot be used in function calls")
|
||||
};
|
||||
parameterStrings.Add($"{qbeParameterType} {result}");
|
||||
}
|
||||
|
||||
var funcName = _funcNames[funcDefinition];
|
||||
|
||||
if (funcDefinition.ReturnType is not NubVoidType)
|
||||
var funcPointer = GenerateExpression(funcCall.Expression);
|
||||
|
||||
if (funcType.ReturnType is not NubVoidType)
|
||||
{
|
||||
var outputName = GenVarName();
|
||||
_builder.AppendLine($" {outputName} {QBEAssign(funcCall.Type)} call {funcName}({string.Join(", ", parameterStrings)})");
|
||||
_builder.AppendLine($" {outputName} {QBEAssign(funcCall.Type)} call {funcPointer}({string.Join(", ", parameterStrings)})");
|
||||
return outputName;
|
||||
}
|
||||
else
|
||||
{
|
||||
_builder.AppendLine($" call {funcName}({string.Join(", ", parameterStrings)})");
|
||||
_builder.AppendLine($" call {funcPointer}({string.Join(", ", parameterStrings)})");
|
||||
return "fuck";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,10 @@ using Nub.Lang.Frontend.Typing;
|
||||
|
||||
namespace Nub.Lang.Frontend.Parsing.Definitions;
|
||||
|
||||
public class FuncParameter(string name, NubType type, bool variadic)
|
||||
public class FuncParameter(string name, NubType type)
|
||||
{
|
||||
public string Name { get; } = name;
|
||||
public NubType Type { get; } = type;
|
||||
public bool Variadic { get; } = variadic;
|
||||
|
||||
public override string ToString() => $"{Name}: {Type}";
|
||||
}
|
||||
|
||||
@@ -2,11 +2,10 @@
|
||||
|
||||
namespace Nub.Lang.Frontend.Parsing.Expressions;
|
||||
|
||||
public class FuncCallNode(IReadOnlyList<Token> tokens, string @namespace, string name, List<ExpressionNode> parameters) : ExpressionNode(tokens)
|
||||
public class FuncCallNode(IReadOnlyList<Token> tokens, ExpressionNode expression, List<ExpressionNode> parameters) : ExpressionNode(tokens)
|
||||
{
|
||||
public string Namespace { get; } = @namespace;
|
||||
public string Name { get; } = name;
|
||||
public ExpressionNode Expression = expression;
|
||||
public List<ExpressionNode> Parameters { get; } = parameters;
|
||||
|
||||
public override string ToString() => $"{Name}::{Name}()";
|
||||
public override string ToString() => $"{Expression}({string.Join(", ", Parameters)})";
|
||||
}
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
namespace Nub.Lang.Frontend.Parsing.Expressions;
|
||||
|
||||
public class IdentifierNode(IReadOnlyList<Token> tokens, string identifier) : LValueNode(tokens)
|
||||
public class IdentifierNode(IReadOnlyList<Token> tokens, string @namespace, string name) : LValueNode(tokens)
|
||||
{
|
||||
public string Identifier { get; } = identifier;
|
||||
public string Namespace { get; } = @namespace;
|
||||
public string Name { get; } = name;
|
||||
|
||||
public override string ToString() => Identifier;
|
||||
public override string ToString() => Name;
|
||||
}
|
||||
@@ -167,19 +167,11 @@ public class Parser
|
||||
|
||||
private FuncParameter ParseFuncParameter()
|
||||
{
|
||||
var variadic = false;
|
||||
if (TryExpectSymbol(Symbol.Period))
|
||||
{
|
||||
ExpectSymbol(Symbol.Period);
|
||||
ExpectSymbol(Symbol.Period);
|
||||
variadic = true;
|
||||
}
|
||||
|
||||
var name = ExpectIdentifier();
|
||||
ExpectSymbol(Symbol.Colon);
|
||||
var type = ParseType();
|
||||
|
||||
return new FuncParameter(name.Value, type, variadic);
|
||||
return new FuncParameter(name.Value, type);
|
||||
}
|
||||
|
||||
private StatementNode ParseStatement()
|
||||
@@ -430,58 +422,15 @@ public class Parser
|
||||
}
|
||||
case IdentifierToken identifier:
|
||||
{
|
||||
var next = Peek();
|
||||
switch (next.Value)
|
||||
var @namespace = _namespace;
|
||||
var name = identifier.Value;
|
||||
if (TryExpectSymbol(Symbol.DoubleColon))
|
||||
{
|
||||
case SymbolToken { Symbol: Symbol.DoubleColon }:
|
||||
{
|
||||
Next();
|
||||
var name = ExpectIdentifier();
|
||||
ExpectSymbol(Symbol.OpenParen);
|
||||
var parameters = new List<ExpressionNode>();
|
||||
while (!TryExpectSymbol(Symbol.CloseParen))
|
||||
{
|
||||
parameters.Add(ParseExpression());
|
||||
if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var nextToken) && nextToken is not SymbolToken { Symbol: Symbol.CloseParen })
|
||||
{
|
||||
_diagnostics.Add(Diagnostic
|
||||
.Warning("Missing comma between function arguments")
|
||||
.WithHelp("Add a ',' to separate arguments")
|
||||
.At(nextToken)
|
||||
.Build());
|
||||
}
|
||||
}
|
||||
|
||||
expr = new FuncCallNode(GetTokensForNode(startIndex), identifier.Value, name.Value, parameters);
|
||||
break;
|
||||
}
|
||||
case SymbolToken { Symbol: Symbol.OpenParen }:
|
||||
{
|
||||
Next();
|
||||
var parameters = new List<ExpressionNode>();
|
||||
while (!TryExpectSymbol(Symbol.CloseParen))
|
||||
{
|
||||
parameters.Add(ParseExpression());
|
||||
if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var nextToken) && nextToken is not SymbolToken { Symbol: Symbol.CloseParen })
|
||||
{
|
||||
_diagnostics.Add(Diagnostic
|
||||
.Warning("Missing comma between function arguments")
|
||||
.WithHelp("Add a ',' to separate arguments")
|
||||
.At(nextToken)
|
||||
.Build());
|
||||
}
|
||||
}
|
||||
|
||||
expr = new FuncCallNode(GetTokensForNode(startIndex), _namespace, identifier.Value, parameters);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
expr = new IdentifierNode(GetTokensForNode(startIndex), identifier.Value);
|
||||
break;
|
||||
}
|
||||
@namespace = identifier.Value;
|
||||
name = ExpectIdentifier().Value;
|
||||
}
|
||||
|
||||
expr = new IdentifierNode(GetTokensForNode(startIndex), @namespace, name);
|
||||
break;
|
||||
}
|
||||
case SymbolToken symbolToken:
|
||||
@@ -628,6 +577,26 @@ public class Parser
|
||||
continue;
|
||||
}
|
||||
|
||||
if (TryExpectSymbol(Symbol.OpenParen))
|
||||
{
|
||||
var parameters = new List<ExpressionNode>();
|
||||
while (!TryExpectSymbol(Symbol.CloseParen))
|
||||
{
|
||||
parameters.Add(ParseExpression());
|
||||
if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var nextToken) && nextToken is not SymbolToken { Symbol: Symbol.CloseParen })
|
||||
{
|
||||
_diagnostics.Add(Diagnostic
|
||||
.Warning("Missing comma between function arguments")
|
||||
.WithHelp("Add a ',' to separate arguments")
|
||||
.At(nextToken)
|
||||
.Build());
|
||||
}
|
||||
}
|
||||
|
||||
expr = new FuncCallNode(GetTokensForNode(startIndex), expr, parameters);
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -688,6 +657,29 @@ public class Parser
|
||||
var baseType = ParseType();
|
||||
return new NubPointerType(baseType);
|
||||
}
|
||||
|
||||
if (TryExpectSymbol(Symbol.Func))
|
||||
{
|
||||
ExpectSymbol(Symbol.OpenParen);
|
||||
List<NubType> parameters = [];
|
||||
while (!TryExpectSymbol(Symbol.CloseParen))
|
||||
{
|
||||
var parameter = ParseType();
|
||||
parameters.Add(parameter);
|
||||
if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var nextToken) && nextToken is not SymbolToken { Symbol: Symbol.CloseParen })
|
||||
{
|
||||
_diagnostics.Add(Diagnostic
|
||||
.Warning("Missing comma between func type arguments")
|
||||
.WithHelp("Add a ',' to separate arguments")
|
||||
.At(nextToken)
|
||||
.Build());
|
||||
}
|
||||
}
|
||||
|
||||
var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new NubVoidType();
|
||||
|
||||
return new NubFuncType(returnType, parameters);
|
||||
}
|
||||
|
||||
if (TryExpectSymbol(Symbol.OpenBracket))
|
||||
{
|
||||
|
||||
@@ -48,6 +48,27 @@ public abstract class NubType
|
||||
public abstract override string ToString();
|
||||
}
|
||||
|
||||
public class NubFuncType(NubType returnType, List<NubType> parameters) : NubType
|
||||
{
|
||||
public NubType ReturnType { get; } = returnType;
|
||||
public List<NubType> Parameters { get; } = parameters;
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is NubFuncType other && other.ReturnType.Equals(ReturnType) && other.Parameters.SequenceEqual(Parameters);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(ReturnType, Parameters);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"func({string.Join(", ", Parameters)}): {ReturnType}";
|
||||
}
|
||||
}
|
||||
|
||||
public class NubStructType(string @namespace, string name) : NubType
|
||||
{
|
||||
public string Namespace { get; } = @namespace;
|
||||
|
||||
@@ -169,7 +169,7 @@ public class TypeChecker
|
||||
|
||||
private void TypeCheckVariableAssignment(VariableAssignmentNode variableAssignment)
|
||||
{
|
||||
if (!_variables.TryGetValue(variableAssignment.Identifier.Identifier, out var variable))
|
||||
if (!_variables.TryGetValue(variableAssignment.Identifier.Name, out var variable))
|
||||
{
|
||||
ReportError($"Variable '{variableAssignment.Identifier}' is not declared", variableAssignment);
|
||||
return;
|
||||
@@ -243,48 +243,34 @@ public class TypeChecker
|
||||
return new NubFixedArrayType(fixedArrayInitializer.ElementType, fixedArrayInitializer.Capacity);
|
||||
}
|
||||
|
||||
private NubType? TypeCheckFuncCall(FuncCallNode funcCall, Node node)
|
||||
private NubType? TypeCheckFuncCall(FuncCallNode funcCall)
|
||||
{
|
||||
var funcDefinition = LookupFuncSignature(funcCall.Namespace, funcCall.Name);
|
||||
if (funcDefinition == null)
|
||||
var identType = TypeCheckExpression(funcCall.Expression);
|
||||
if (identType is not NubFuncType funcType)
|
||||
{
|
||||
ReportError($"Function '{funcCall}' is not defined", node);
|
||||
ReportError("Cannot call function on non-function type", funcCall);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (funcDefinition.Parameters.Take(funcDefinition.Parameters.Count - 1).Any(x => x.Variadic))
|
||||
if (funcCall.Parameters.Count != funcType.Parameters.Count)
|
||||
{
|
||||
ReportError($"Function '{funcCall}' has multiple variadic parameters", node);
|
||||
return null;
|
||||
ReportError($"{funcType} expects {funcType.Parameters.Count} arguments, but was called with {funcType.Parameters.Count} arguments", funcCall);
|
||||
}
|
||||
|
||||
|
||||
for (var i = 0; i < funcCall.Parameters.Count; i++)
|
||||
{
|
||||
NubType paramType;
|
||||
if (i < funcDefinition.Parameters.Count)
|
||||
{
|
||||
paramType = funcDefinition.Parameters[i].Type;
|
||||
}
|
||||
else if (funcDefinition.Parameters.LastOrDefault()?.Variadic ?? false)
|
||||
{
|
||||
paramType = funcDefinition.Parameters[^1].Type;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReportError($"Function '{funcCall}' does not take {funcCall.Parameters.Count} parameters", node);
|
||||
continue;
|
||||
}
|
||||
|
||||
var argType = TypeCheckExpression(funcCall.Parameters[i], paramType);
|
||||
if (argType == null) return null;
|
||||
var parameter = funcCall.Parameters[i];
|
||||
var parameterType = TypeCheckExpression(parameter);
|
||||
if (parameterType == null) return null;
|
||||
|
||||
if (!NubType.IsCompatibleWith(argType, paramType))
|
||||
if (!NubType.IsCompatibleWith(parameterType, funcType.Parameters[i]))
|
||||
{
|
||||
ReportError($"Parameter {i + 1} of function '{funcCall}' expects type '{paramType}', but got '{argType}'", funcCall.Parameters[i]);
|
||||
ReportError($"'{parameterType}' does not match expected type {funcType.Parameters[i]}", funcCall);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return funcDefinition.ReturnType;
|
||||
return funcType.ReturnType;
|
||||
}
|
||||
|
||||
private void TypeCheckIf(IfNode ifNode)
|
||||
@@ -364,7 +350,7 @@ public class TypeChecker
|
||||
BinaryExpressionNode binaryExpr => TypeCheckBinaryExpression(binaryExpr),
|
||||
DereferenceNode dereference => TypeCheckDereference(dereference),
|
||||
FixedArrayInitializerNode fixedArray => TypeCheckFixedInitializerArray(fixedArray),
|
||||
FuncCallNode funcCallExpr => TypeCheckFuncCall(funcCallExpr, funcCallExpr),
|
||||
FuncCallNode funcCallExpr => TypeCheckFuncCall(funcCallExpr),
|
||||
StructInitializerNode structInit => TypeCheckStructInitializer(structInit),
|
||||
UnaryExpressionNode unaryExpression => TypeCheckUnaryExpression(unaryExpression),
|
||||
MemberAccessNode memberAccess => TypeCheckMemberAccess(memberAccess),
|
||||
@@ -447,13 +433,24 @@ public class TypeChecker
|
||||
|
||||
private NubType? TypeCheckIdentifier(IdentifierNode identifier)
|
||||
{
|
||||
if (!_variables.TryGetValue(identifier.Identifier, out var varType))
|
||||
var result = _variables.GetValueOrDefault(identifier.Name);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
ReportError($"Variable '{identifier.Identifier}' is not defined", identifier);
|
||||
var func = LookupFuncSignature(identifier.Namespace, identifier.Name);
|
||||
if (func != null)
|
||||
{
|
||||
result = new NubFuncType(func.ReturnType, func.Parameters.Select(p => p.Type).ToList());
|
||||
}
|
||||
}
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
ReportError($"Identifier '{identifier.Name}' is not defined", identifier);
|
||||
return null;
|
||||
}
|
||||
|
||||
return varType;
|
||||
return result;
|
||||
}
|
||||
|
||||
private NubType? TypeCheckAddressOf(AddressOfNode addressOf)
|
||||
|
||||
Reference in New Issue
Block a user