diff --git a/example/src/main.nub b/example/src/main.nub index 0e933a0..100b14b 100644 --- a/example/src/main.nub +++ b/example/src/main.nub @@ -1,37 +1,13 @@ // c extern func puts(text: cstring) -interface Printable -{ - func print() - func test() -} - -struct Human : Printable -{ - name: cstring - age: u32 - - func print() - { - puts(this.name) - } - - func test() - { - puts("test") - } -} - func main(args: []cstring): i64 { - let x = struct Human { - name = "Oliver" - age = 23 - } - - x.print() - x.test() - + let x: i32 = 23 + test(x) return 0 } + +func test(test: u8) +{ +} \ No newline at end of file diff --git a/src/compiler/NubLang/Generation/QBE/QBEGenerator.cs b/src/compiler/NubLang/Generation/QBE/QBEGenerator.cs index c6503c5..8cfba73 100644 --- a/src/compiler/NubLang/Generation/QBE/QBEGenerator.cs +++ b/src/compiler/NubLang/Generation/QBE/QBEGenerator.cs @@ -600,6 +600,8 @@ public class QBEGenerator FuncCallNode funcCall => EmitFuncCall(funcCall), InterfaceFuncCallNode interfaceFuncCall => EmitInterfaceFuncCall(interfaceFuncCall), InterfaceInitializerNode interfaceInitializer => EmitInterfaceInitializer(interfaceInitializer), + ConvertIntNode convertInt => EmitConvertInt(convertInt), + ConvertFloatNode convertFloat => EmitConvertFloat(convertFloat), ExternFuncIdentNode externFuncIdent => EmitExternFuncIdent(externFuncIdent), LocalFuncIdentNode localFuncIdent => EmitLocalFuncIdent(localFuncIdent), VariableIdentNode variableIdent => EmitVariableIdent(variableIdent), @@ -1118,6 +1120,59 @@ public class QBEGenerator return destination; } + private string EmitConvertInt(ConvertIntNode convertInt) + { + var value = EmitExpression(convertInt.Value); + + if (convertInt.ValueType == convertInt.TargetType || convertInt.ValueType.Width > convertInt.TargetType.Width) + { + return value; + } + + var method = convertInt.ValueType.Signed switch + { + true => convertInt.ValueType.Width switch + { + 8 => "extsb", + 16 => "extsh", + 32 => "extsw", + _ => throw new ArgumentOutOfRangeException() + }, + false => convertInt.ValueType.Width switch + { + 8 => "extub", + 16 => "extuh", + 32 => "extuw", + _ => throw new ArgumentOutOfRangeException() + } + }; + + var result = TmpName(); + _writer.Indented($"{result} {QBEAssign(convertInt.TargetType)} {method} {value}"); + return result; + } + + private string EmitConvertFloat(ConvertFloatNode convertFloat) + { + var value = EmitExpression(convertFloat.Value); + + if (convertFloat.ValueType == convertFloat.TargetType) + { + return value; + } + + var method = convertFloat.ValueType.Width switch + { + 32 => "exts", + 64 => "truncd", + _ => throw new ArgumentOutOfRangeException() + }; + + var result = TmpName(); + _writer.Indented($"{result} {QBEAssign(convertFloat.TargetType)} {method} {value}"); + return result; + } + private string EmitFuncCall(FuncCallNode funcCall) { var funcPointer = EmitExpression(funcCall.Expression); diff --git a/src/compiler/NubLang/TypeChecking/Node/ExpressionNode.cs b/src/compiler/NubLang/TypeChecking/Node/ExpressionNode.cs index 03f629c..b8ca51e 100644 --- a/src/compiler/NubLang/TypeChecking/Node/ExpressionNode.cs +++ b/src/compiler/NubLang/TypeChecking/Node/ExpressionNode.cs @@ -59,4 +59,8 @@ public record StructInitializerNode(StructTypeNode StructType, Dictionary i64 etc. - switch (expression.Type) + if (expression.Type is StructTypeNode structType && targetType is InterfaceTypeNode interfaceType) { - case StructTypeNode structType when targetType is InterfaceTypeNode interfaceType: - { - return new InterfaceInitializerNode(interfaceType, interfaceType, structType, expression); - } + return new InterfaceInitializerNode(interfaceType, interfaceType, structType, expression); + } + + if (expression.Type is IntTypeNode sourceIntType && targetType is IntTypeNode targetIntType) + { + // if ((sourceIntType.Width < targetIntType.Width) || (sourceIntType.Width == targetIntType.Width && sourceIntType.Signed != targetIntType.Signed)) + // { + return new ConvertIntNode(targetIntType, expression, targetIntType, sourceIntType); + // } + } + + if (expression.Type is FloatTypeNode sourceFloatType && targetType is FloatTypeNode targetFloatType) + { + // if (sourceFloatType.Width < targetFloatType.Width) + // { + return new ConvertFloatNode(targetFloatType, expression, targetFloatType, sourceFloatType); + // } } throw new TypeCheckerException(Diagnostic.Error($"Cannot convert {expression.Type} to {targetType}").Build()); @@ -316,7 +328,7 @@ public sealed class TypeChecker { throw new TypeCheckerException(Diagnostic.Error("Cannot take address of rvalue").Build()); } - + return new AddressOfNode(new PointerTypeNode(inner.Type), lValueInner); }