summaryrefslogtreecommitdiff
path: root/src/main/java/com/seaofnodes/simple/parser/Conversions.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/seaofnodes/simple/parser/Conversions.java')
-rw-r--r--src/main/java/com/seaofnodes/simple/parser/Conversions.java72
1 files changed, 72 insertions, 0 deletions
diff --git a/src/main/java/com/seaofnodes/simple/parser/Conversions.java b/src/main/java/com/seaofnodes/simple/parser/Conversions.java
new file mode 100644
index 00000000..d50e2031
--- /dev/null
+++ b/src/main/java/com/seaofnodes/simple/parser/Conversions.java
@@ -0,0 +1,72 @@
+package com.seaofnodes.simple.parser;
+
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.type.*;
+
+/** Shared declaration, assignment, and return conversions. */
+final class Conversions {
+ private final Parser P;
+
+ Conversions(Parser P) { this.P = P; }
+
+ // Widen ints to floats; narrow wide int types.
+ // Early error if types do not match variable.
+ Node convertExpr( Node expr, Type t ) {
+ if( !expr._type.accessISA(t) )
+ throw P.error("Type "+expr._type.str()+" is not of declared type "+t.str());
+ if( t instanceof TypeMemPtr tmp && tmp.isFinal() )
+ expr = P.peep(new ReadOnlyNode(expr));
+ // A FunPtr carries the semantic edge to its function's Return. Do not
+ // hide that edge behind a Convert which can fold to a plain constant.
+ if( expr instanceof FunPtrNode && t instanceof TypeFunPtr )
+ return expr;
+ // Auto-widen array to i64 (cast ptr to raw int bits)
+ if( t == TypeInteger.BOT && expr._type instanceof TypeMemPtr tmp && tmp._obj.isAry() )
+ return P.peep(new AddNode(P.peep(new PtrToIntNode(expr)),Parser.off(tmp._obj,"[]")));
+ // Widen ints to floats, narrow wide types
+ return P.peep(new ConvertNode(t,expr));
+ }
+
+ // Inferred `var` declarations describe writable slots, not the exact
+ // value used to initialize them. Explicitly typed locals retain the
+ // user's nullability and numeric-width guarantees; `val` retains the
+ // initializer's precise type.
+ static Type mutableInferredType(Type t) {
+ return switch( t ) {
+ case TypeInteger ti -> TypeInteger.BOT;
+ case TypeFloat tf -> TypeFloat.F64;
+ case TypeMemPtr tmp -> tmp.makeVar();
+ case TypeFunPtr tfp -> tfp;
+ case TypeConAry<?> a -> a;
+ case TypePtr ptr -> TypePtr.PTR;
+ case TypeScalar ts -> TypeScalar.BOT;
+ default -> t;
+ };
+ }
+
+ Type constructorFieldType(Type t) {
+ if( t instanceof TypeMemPtr ptr && ptr._obj.isConAry() ) {
+ TypeStruct declared = (TypeStruct)Parser.TYPES.get(ptr._obj._name);
+ TypeStruct shape = P.types.typeAry(declared._fields[1]._t,ptr._obj._fields[1]._final);
+ return TypeMemPtr.make((byte)2,shape,false).withAccess(ptr._ro);
+ }
+ return mutableInferredType(t);
+ }
+
+ // Seed an inferred return merge with the declared numeric family instead
+ // of a transient constant/range. Pointer nullability remains part of the
+ // inferred function result and is combined by the later Phi.
+ static Type inferredReturnType(Type t) {
+ return switch( t ) {
+ case TypeInteger ti -> TypeInteger.BOT;
+ case TypeFloat tf -> TypeFloat.F64;
+ default -> t;
+ };
+ }
+
+ Node widenInt( Node expr, Type t ) {
+ return (expr._type instanceof TypeInteger || expr._type==Type.NIL) && t instanceof TypeFloat
+ ? P.peep(new ToFloatNode(expr)) : expr;
+ }
+
+}