diff --git a/example/interop/c.nub b/example/interop/c.nub index d387515..868164c 100644 --- a/example/interop/c.nub +++ b/example/interop/c.nub @@ -1,13 +1,13 @@ namespace c -extern func printf(fmt: ^u8, ...args: any) +extern func printf(fmt: ^u8, ...args: any): void extern func getchar(): i32 extern func puts(fmt: ^u8) -extern func malloc(size: i64): ^any -extern func calloc(num: i64, size: i64): ^any -extern func realloc(ptr: ^any, size: i64): ^any -extern func free(ptr: ^any) +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 diff --git a/example/main.nub b/example/main.nub index ef23a53..5e946ff 100644 --- a/example/main.nub +++ b/example/main.nub @@ -4,7 +4,7 @@ struct Human { age: ^u64 } -export func main(args: []^string) { +export func main(args: []^string): i64 { let x = [3]f64 x[0] = 1 @@ -14,4 +14,6 @@ export func main(args: []^string) { c::printf("%f\n", x[0]) c::printf("%f\n", x[1]) c::printf("%f\n", x[2]) + + return 0 } diff --git a/src/lang/Nub.Lang/Diagnostics/Diagnostic.cs b/src/lang/Nub.Lang/Diagnostics/Diagnostic.cs index f53dca8..6a859cc 100644 --- a/src/lang/Nub.Lang/Diagnostics/Diagnostic.cs +++ b/src/lang/Nub.Lang/Diagnostics/Diagnostic.cs @@ -116,7 +116,7 @@ public class Diagnostic var lineNumWidth = Math.Min(endLine + contextLines, lines.Length).ToString().Length; var contextStart = Math.Max(1, startLine - contextLines); - var contextEnd = Math.Min(lines.Length + 1, endLine + contextLines); + var contextEnd = Math.Min(lines.Length, endLine + contextLines); var contextWidth = 0; for (var i = contextStart; i <= contextEnd; i++) diff --git a/src/lang/Nub.Lang/Frontend/Generation/Generator.cs b/src/lang/Nub.Lang/Frontend/Generation/Generator.cs index 89c188a..3c34824 100644 --- a/src/lang/Nub.Lang/Frontend/Generation/Generator.cs +++ b/src/lang/Nub.Lang/Frontend/Generation/Generator.cs @@ -84,68 +84,6 @@ public class Generator return _builder.ToString(); } - private enum TypeContext - { - FuncDef, - FuncCall, - } - - private static string QBEType(NubType type, TypeContext context) - { - return context switch - { - TypeContext.FuncDef => type switch - { - NubArrayType => "l", - NubPointerType => "l", - NubPrimitiveType primitiveType => primitiveType.Kind switch - { - PrimitiveTypeKind.I64 => "l", - PrimitiveTypeKind.I32 => "w", - PrimitiveTypeKind.I16 => "sh", - PrimitiveTypeKind.I8 => "sb", - PrimitiveTypeKind.U64 => "l", - PrimitiveTypeKind.U32 => "w", - PrimitiveTypeKind.U16 => "uh", - PrimitiveTypeKind.U8 => "ub", - PrimitiveTypeKind.F64 => "d", - PrimitiveTypeKind.F32 => "s", - PrimitiveTypeKind.Bool => "w", - PrimitiveTypeKind.Any => throw new NotSupportedException("any type cannot be used in function definitions"), - _ => throw new ArgumentOutOfRangeException() - }, - NubStructType structType => $":{structType.Namespace}_{structType.Name}", - NubFixedArrayType => "l", - _ => throw new ArgumentOutOfRangeException(nameof(type)) - }, - TypeContext.FuncCall => type switch - { - NubArrayType => "l", - NubPointerType => "l", - NubPrimitiveType pointerType => pointerType.Kind switch - { - PrimitiveTypeKind.I64 => "l", - PrimitiveTypeKind.I32 => "w", - PrimitiveTypeKind.I16 => "sh", - PrimitiveTypeKind.I8 => "sb", - PrimitiveTypeKind.U64 => "l", - PrimitiveTypeKind.U32 => "w", - PrimitiveTypeKind.U16 => "uh", - PrimitiveTypeKind.U8 => "ub", - PrimitiveTypeKind.F64 => "d", - PrimitiveTypeKind.F32 => "s", - PrimitiveTypeKind.Bool => "w", - PrimitiveTypeKind.Any => "l", - _ => throw new ArgumentOutOfRangeException() - }, - NubStructType structType => $":{structType.Namespace}_{structType.Name}", - NubFixedArrayType => "l", - _ => throw new ArgumentOutOfRangeException(nameof(type)) - }, - _ => throw new ArgumentOutOfRangeException(nameof(context), context, null) - }; - } - private static string QBEStore(NubType type) { return $"store{type switch @@ -165,12 +103,11 @@ public class Generator PrimitiveTypeKind.F64 => "d", PrimitiveTypeKind.F32 => "s", PrimitiveTypeKind.Bool => "w", - PrimitiveTypeKind.Any => throw new NotSupportedException("any type cannot be used in store instructions"), - _ => throw new ArgumentOutOfRangeException() + _ => throw new UnreachableException() }, NubStructType => "l", NubFixedArrayType => "l", - _ => throw new ArgumentOutOfRangeException(nameof(type)) + _ => throw new NotSupportedException($"'{type}' type cannot be used in store instructions") }}"; } @@ -193,12 +130,11 @@ public class Generator PrimitiveTypeKind.F64 => "d", PrimitiveTypeKind.F32 => "s", PrimitiveTypeKind.Bool => "w", - PrimitiveTypeKind.Any => throw new NotSupportedException("any type cannot be used in load instructions"), - _ => throw new ArgumentOutOfRangeException() + _ => throw new UnreachableException() }, NubStructType => "l", NubFixedArrayType => "l", - _ => throw new ArgumentOutOfRangeException(nameof(type)) + _ => throw new NotSupportedException($"'{type}' type cannot be used in load instructions") }}"; } @@ -221,12 +157,11 @@ public class Generator PrimitiveTypeKind.F64 => "d", PrimitiveTypeKind.F32 => "s", PrimitiveTypeKind.Bool => "w", - PrimitiveTypeKind.Any => throw new NotSupportedException("any type cannot be used in variables"), - _ => throw new ArgumentOutOfRangeException() + _ => throw new UnreachableException() }, NubStructType => "l", NubFixedArrayType => "l", - _ => throw new ArgumentOutOfRangeException(nameof(type)) + _ => throw new NotSupportedException($"'{type}' type cannot be used in variables") }}"; } @@ -240,7 +175,6 @@ public class Generator { case PrimitiveTypeKind.I64: case PrimitiveTypeKind.U64: - case PrimitiveTypeKind.Any: return 8; case PrimitiveTypeKind.I32: case PrimitiveTypeKind.U32: @@ -304,18 +238,59 @@ public class Generator } _builder.Append("function "); - if (node.ReturnType.HasValue) + if (node.ReturnType is not NubVoidType) { - _builder.Append($"{QBEType(node.ReturnType.Value, TypeContext.FuncDef)} "); - } - else if (!node.ReturnType.HasValue && node.Name == "main") - { - _builder.Append("l "); + _builder.Append(node.ReturnType switch + { + NubArrayType => "l", + NubPointerType => "l", + NubPrimitiveType primitiveType => primitiveType.Kind switch + { + PrimitiveTypeKind.I64 => "l", + PrimitiveTypeKind.I32 => "w", + PrimitiveTypeKind.I16 => "sh", + PrimitiveTypeKind.I8 => "sb", + PrimitiveTypeKind.U64 => "l", + PrimitiveTypeKind.U32 => "w", + PrimitiveTypeKind.U16 => "uh", + PrimitiveTypeKind.U8 => "ub", + PrimitiveTypeKind.F64 => "d", + PrimitiveTypeKind.F32 => "s", + PrimitiveTypeKind.Bool => "w", + _ => throw new UnreachableException() + }, + NubStructType structType => $":{structType.Namespace}_{structType.Name}", + NubFixedArrayType => "l", + _ => throw new NotSupportedException($"'{node.ReturnType}' type cannot be used as a function return type") + }); + _builder.Append(' '); } _builder.Append(_funcNames[node]); - var parameterStrings = node.Parameters.Select(parameter => parameter.Variadic ? "..." : $"{QBEType(parameter.Type, TypeContext.FuncDef)} %{parameter.Name}"); + var parameterStrings = node.Parameters.Select(parameter => parameter.Variadic ? "..." : $"{parameter.Type switch + { + NubArrayType => "l", + NubPointerType => "l", + NubPrimitiveType primitiveType => primitiveType.Kind switch + { + PrimitiveTypeKind.I64 => "l", + PrimitiveTypeKind.I32 => "w", + PrimitiveTypeKind.I16 => "sh", + PrimitiveTypeKind.I8 => "sb", + PrimitiveTypeKind.U64 => "l", + PrimitiveTypeKind.U32 => "w", + PrimitiveTypeKind.U16 => "uh", + PrimitiveTypeKind.U8 => "ub", + PrimitiveTypeKind.F64 => "d", + PrimitiveTypeKind.F32 => "s", + PrimitiveTypeKind.Bool => "w", + _ => throw new UnreachableException() + }, + NubStructType structType => $":{structType.Namespace}_{structType.Name}", + NubFixedArrayType => "l", + _ => throw new NotSupportedException($"'{parameter.Type}' type cannot be used as a function parameter type") + }} %{parameter.Name}"); _builder.AppendLine($"({string.Join(", ", parameterStrings)}) {{"); _builder.AppendLine("@start"); @@ -324,25 +299,25 @@ public class Generator { var parameterName = parameter.Name; - switch (QBEType(parameter.Type, TypeContext.FuncDef)) - { - case "sb": - parameterName = GenVarName(); - _builder.AppendLine($" {parameterName} =w extsb %{parameter.Name}"); - break; - case "ub": - parameterName = GenVarName(); - _builder.AppendLine($" {parameterName} =w extub %{parameter.Name}"); - break; - case "sh": - parameterName = GenVarName(); - _builder.AppendLine($" {parameterName} =w extsh %{parameter.Name}"); - break; - case "uh": - parameterName = GenVarName(); - _builder.AppendLine($" {parameterName} =w extuh %{parameter.Name}"); - break; - } + // switch (QBEType(parameter.Type)) + // { + // case "sb": + // parameterName = GenVarName(); + // _builder.AppendLine($" {parameterName} =w extsb %{parameter.Name}"); + // break; + // case "ub": + // parameterName = GenVarName(); + // _builder.AppendLine($" {parameterName} =w extub %{parameter.Name}"); + // break; + // case "sh": + // parameterName = GenVarName(); + // _builder.AppendLine($" {parameterName} =w extsh %{parameter.Name}"); + // break; + // case "uh": + // parameterName = GenVarName(); + // _builder.AppendLine($" {parameterName} =w extuh %{parameter.Name}"); + // break; + // } if (IsLargeType(parameter.Type)) { @@ -364,13 +339,7 @@ public class Generator if (node.Body.Statements.LastOrDefault() is not ReturnNode) { - if (!node.ReturnType.HasValue && node.Name == "main") - { - _builder.AppendLine(); - _builder.AppendLine(" # Implicit return for main"); - _builder.AppendLine(" ret 0"); - } - else if (!node.ReturnType.HasValue) + if (node.ReturnType is NubVoidType) { _builder.AppendLine(); _builder.AppendLine(" # Implicit return"); @@ -386,40 +355,34 @@ public class Generator _builder.Append($"type :{structDefinition.Namespace}_{structDefinition.Name} = {{ "); foreach (var structDefinitionField in structDefinition.Fields) { - var fieldDefinition = GenerateFieldType(structDefinitionField.Type); - _builder.Append(fieldDefinition + ", "); + var fieldQbeType = structDefinitionField.Type switch + { + NubArrayType => "l", + NubPointerType => "l", + NubPrimitiveType primitiveType => primitiveType.Kind switch + { + PrimitiveTypeKind.I64 => "l", + PrimitiveTypeKind.I32 => "w", + PrimitiveTypeKind.I16 => "h", + PrimitiveTypeKind.I8 => "b", + PrimitiveTypeKind.U64 => "l", + PrimitiveTypeKind.U32 => "w", + PrimitiveTypeKind.U16 => "h", + PrimitiveTypeKind.U8 => "b", + PrimitiveTypeKind.F64 => "d", + PrimitiveTypeKind.F32 => "s", + PrimitiveTypeKind.Bool => "w", + _ => throw new UnreachableException() + }, + NubStructType structType => $":{structType.Namespace}_{structType.Name}", + NubFixedArrayType fixedArrayType => $"b {SizeOf(fixedArrayType)}", + _ => throw new NotSupportedException($"'{structDefinitionField.Type}' type cannot be used in structs") + }; + _builder.Append(fieldQbeType + ", "); } _builder.AppendLine("}"); } - private string GenerateFieldType(NubType type) - { - return type switch - { - NubArrayType => "l", - NubPointerType => "l", - NubPrimitiveType primitiveType => primitiveType.Kind switch - { - PrimitiveTypeKind.I64 => "l", - PrimitiveTypeKind.I32 => "w", - PrimitiveTypeKind.I16 => "h", - PrimitiveTypeKind.I8 => "b", - PrimitiveTypeKind.U64 => "l", - PrimitiveTypeKind.U32 => "w", - PrimitiveTypeKind.U16 => "h", - PrimitiveTypeKind.U8 => "b", - PrimitiveTypeKind.F64 => "d", - PrimitiveTypeKind.F32 => "s", - PrimitiveTypeKind.Bool => "w", - PrimitiveTypeKind.Any => throw new NotSupportedException("any type cannot be used in structs"), - _ => throw new ArgumentOutOfRangeException() - }, - NubStructType structType => $":{structType.Namespace}_{structType.Name}", - NubFixedArrayType fixedArrayType => $"b {SizeOf(fixedArrayType)}", - _ => throw new ArgumentOutOfRangeException(nameof(type)) - }; - } - private void GenerateStatement(StatementNode statement) { switch (statement) @@ -1739,13 +1702,35 @@ public class Generator var parameter = funcCall.Parameters[i]; var result = GenerateExpression(parameter); - var qbeParameterType = QBEType(parameter.Type, TypeContext.FuncCall); + var qbeParameterType = parameter.Type switch + { + NubArrayType => "l", + NubPointerType => "l", + NubPrimitiveType pointerType => pointerType.Kind switch + { + PrimitiveTypeKind.I64 => "l", + PrimitiveTypeKind.I32 => "w", + PrimitiveTypeKind.I16 => "sh", + PrimitiveTypeKind.I8 => "sb", + PrimitiveTypeKind.U64 => "l", + PrimitiveTypeKind.U32 => "w", + PrimitiveTypeKind.U16 => "uh", + PrimitiveTypeKind.U8 => "ub", + PrimitiveTypeKind.F64 => "d", + PrimitiveTypeKind.F32 => "s", + PrimitiveTypeKind.Bool => "w", + _ => throw new ArgumentOutOfRangeException() + }, + NubStructType structType => $":{structType.Namespace}_{structType.Name}", + NubFixedArrayType => "l", + _ => throw new NotSupportedException($"'{parameter.Type}' type cannot be used in function calls") + }; parameterStrings.Add($"{qbeParameterType} {result}"); } var funcName = _funcNames[funcDefinition]; - if (funcDefinition.ReturnType.HasValue) + if (funcDefinition.ReturnType is not NubVoidType) { var outputName = GenVarName(); _builder.AppendLine($" {outputName} {QBEAssign(funcCall.Type)} call {funcName}({string.Join(", ", parameterStrings)})"); diff --git a/src/lang/Nub.Lang/Frontend/Parsing/Definitions/FuncDefinitionNode.cs b/src/lang/Nub.Lang/Frontend/Parsing/Definitions/FuncDefinitionNode.cs index ae6b63f..19331e9 100644 --- a/src/lang/Nub.Lang/Frontend/Parsing/Definitions/FuncDefinitionNode.cs +++ b/src/lang/Nub.Lang/Frontend/Parsing/Definitions/FuncDefinitionNode.cs @@ -18,30 +18,30 @@ public interface IFuncSignature public string Name { get; } public string Namespace { get; } public List Parameters { get; } - public Optional ReturnType { get; } + public NubType ReturnType { get; } - public string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){(ReturnType.HasValue ? ": " + ReturnType.Value : "")}"; + public string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){": " + ReturnType}"; } -public class LocalFuncDefinitionNode(IReadOnlyList tokens, Optional documentation, string name, string @namespace, List parameters, BlockNode body, Optional returnType, bool exported) : DefinitionNode(tokens, documentation), IFuncSignature +public class LocalFuncDefinitionNode(IReadOnlyList tokens, Optional documentation, string name, string @namespace, List parameters, BlockNode body, NubType returnType, bool exported) : DefinitionNode(tokens, documentation), IFuncSignature { public string Name { get; } = name; public string Namespace { get; } = @namespace; public List Parameters { get; } = parameters; public BlockNode Body { get; } = body; - public Optional ReturnType { get; } = returnType; + public NubType ReturnType { get; } = returnType; public bool Exported { get; } = exported; - public override string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){(ReturnType.HasValue ? ": " + ReturnType.Value : "")}"; + public override string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){": " + ReturnType}"; } -public class ExternFuncDefinitionNode(IReadOnlyList tokens, Optional documentation, string name, string @namespace, string callName, List parameters, Optional returnType) : DefinitionNode(tokens, documentation), IFuncSignature +public class ExternFuncDefinitionNode(IReadOnlyList tokens, Optional documentation, string name, string @namespace, string callName, List parameters, NubType returnType) : DefinitionNode(tokens, documentation), IFuncSignature { public string Name { get; } = name; public string Namespace { get; } = @namespace; public string CallName { get; } = callName; public List Parameters { get; } = parameters; - public Optional ReturnType { get; } = returnType; + public NubType ReturnType { get; } = returnType; - public override string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){(ReturnType.HasValue ? ": " + ReturnType.Value : "")}"; + public override string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){": " + ReturnType}"; } \ No newline at end of file diff --git a/src/lang/Nub.Lang/Frontend/Parsing/Parser.cs b/src/lang/Nub.Lang/Frontend/Parsing/Parser.cs index c4bc676..c408c54 100644 --- a/src/lang/Nub.Lang/Frontend/Parsing/Parser.cs +++ b/src/lang/Nub.Lang/Frontend/Parsing/Parser.cs @@ -99,11 +99,7 @@ public class Parser } } - var returnType = Optional.Empty(); - if (TryExpectSymbol(Symbol.Colon)) - { - returnType = ParseType(); - } + var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new NubVoidType(); var isExtern = modifiers.RemoveAll(x => x.Modifier == Modifier.Extern) > 0; if (isExtern) @@ -665,20 +661,28 @@ public class Parser { if (TryExpectIdentifier(out var name)) { + if (name == "any") + { + return new NubAnyType(); + } + + if (name == "void") + { + return new NubVoidType(); + } + if (NubPrimitiveType.TryParse(name, out var primitiveTypeKind)) { return new NubPrimitiveType(primitiveTypeKind.Value); } - else - { - var @namespace = _namespace; - if (TryExpectSymbol(Symbol.DoubleColon)) - { - @namespace = ExpectIdentifier().Value; - } - return new NubStructType(@namespace, name); + var @namespace = _namespace; + if (TryExpectSymbol(Symbol.DoubleColon)) + { + @namespace = ExpectIdentifier().Value; } + + return new NubStructType(@namespace, name); } if (TryExpectSymbol(Symbol.Caret)) diff --git a/src/lang/Nub.Lang/Frontend/Typing/NubType.cs b/src/lang/Nub.Lang/Frontend/Typing/NubType.cs index 9746334..f67e4e3 100644 --- a/src/lang/Nub.Lang/Frontend/Typing/NubType.cs +++ b/src/lang/Nub.Lang/Frontend/Typing/NubType.cs @@ -6,7 +6,7 @@ public abstract class NubType { public static bool IsCompatibleWith(NubType sourceType, NubType targetType) { - if (targetType.Equals(NubPrimitiveType.Any) || sourceType.Equals(targetType)) + if (targetType is NubAnyType || sourceType.Equals(targetType)) { return true; } @@ -16,11 +16,6 @@ public abstract class NubType return true; } - // if (sourceType.Equals(NubPrimitiveType.String) && targetType is NubArrayType arrayType && IsCompatibleWith(NubPrimitiveType.U8, arrayType.ElementType)) - // { - // return true; - // } - return false; } @@ -136,6 +131,36 @@ public class NubFixedArrayType(NubType elementType, int capacity) : NubType } } +public class NubAnyType : NubType +{ + public override string ToString() => "any"; + + public override bool Equals(object? obj) + { + return obj is NubAnyType; + } + + public override int GetHashCode() + { + return GetType().GetHashCode(); + } +} + +public class NubVoidType : NubType +{ + public override string ToString() => "void"; + + public override bool Equals(object? obj) + { + return obj is NubVoidType; + } + + public override int GetHashCode() + { + return GetType().GetHashCode(); + } +} + public class NubPrimitiveType(PrimitiveTypeKind kind) : NubType { public PrimitiveTypeKind Kind { get; } = kind; @@ -154,7 +179,6 @@ public class NubPrimitiveType(PrimitiveTypeKind kind) : NubType public static NubPrimitiveType F32 => new(PrimitiveTypeKind.F32); public static NubPrimitiveType Bool => new(PrimitiveTypeKind.Bool); - public static NubPrimitiveType Any => new(PrimitiveTypeKind.Any); public static bool TryParse(string s, [NotNullWhen(true)] out PrimitiveTypeKind? kind) { @@ -171,7 +195,6 @@ public class NubPrimitiveType(PrimitiveTypeKind kind) : NubType "f64" => PrimitiveTypeKind.F64, "f32" => PrimitiveTypeKind.F32, "bool" => PrimitiveTypeKind.Bool, - "any" => PrimitiveTypeKind.Any, _ => null }; @@ -206,7 +229,6 @@ public class NubPrimitiveType(PrimitiveTypeKind kind) : NubType PrimitiveTypeKind.F64 => "f64", PrimitiveTypeKind.Bool => "bool", - PrimitiveTypeKind.Any => "any", _ => throw new ArgumentOutOfRangeException(nameof(kind), Kind, null) }; } @@ -224,6 +246,5 @@ public enum PrimitiveTypeKind U8, F64, F32, - Bool, - Any + Bool } \ No newline at end of file diff --git a/src/lang/Nub.Lang/Frontend/Typing/TypeChecker.cs b/src/lang/Nub.Lang/Frontend/Typing/TypeChecker.cs index 91ce8ee..3f4aede 100644 --- a/src/lang/Nub.Lang/Frontend/Typing/TypeChecker.cs +++ b/src/lang/Nub.Lang/Frontend/Typing/TypeChecker.cs @@ -14,14 +14,12 @@ public class TypeChecker private List _sourceFiles = []; private List _diagnostics = []; private NubType? _currentFunctionReturnType; - private bool _hasReturnStatement; public DiagnosticsResult TypeCheck(List sourceFiles) { _variables = new Dictionary(); _diagnostics = []; _currentFunctionReturnType = null; - _hasReturnStatement = false; _sourceFiles = sourceFiles; var externFuncDefinitions = _sourceFiles @@ -85,8 +83,7 @@ public class TypeChecker private void TypeCheckFuncDef(LocalFuncDefinitionNode funcDef) { _variables.Clear(); - _currentFunctionReturnType = funcDef.ReturnType.HasValue ? funcDef.ReturnType.Value : null; - _hasReturnStatement = false; + _currentFunctionReturnType = funcDef.ReturnType; foreach (var param in funcDef.Parameters) { @@ -94,11 +91,6 @@ public class TypeChecker } TypeCheckBlock(funcDef.Body); - - if (_currentFunctionReturnType != null && !_hasReturnStatement) - { - ReportError($"Function '{funcDef.Name}' must return a value of type '{_currentFunctionReturnType}'", funcDef); - } } private void TypeCheckBlock(BlockNode block) @@ -292,7 +284,7 @@ public class TypeChecker } } - return funcDefinition.ReturnType.HasValue ? funcDefinition.ReturnType.Value : NubPrimitiveType.Any; + return funcDefinition.ReturnType; } private void TypeCheckIf(IfNode ifNode) @@ -325,8 +317,6 @@ public class TypeChecker private void TypeCheckReturn(ReturnNode returnNode) { - _hasReturnStatement = true; - if (returnNode.Value.HasValue) { var returnType = TypeCheckExpression(returnNode.Value.Value, _currentFunctionReturnType);