Commits

kevinclancy committed ee915f3

changed the way deduced/accumulated types format tostring. Cleaned and refactored typechecker.fs.

Comments (0)

Files changed (2)

LoveStudio/LuaAnalyzer/Type.fs

         | OverloadTy(tyList) ->
             "overload: " + tyList.ToString()
         | DeducedTy(perm,temp) ->
-            perm.ToString() + " (" + temp.ToString() + ")"
+            perm.ToString() + "(" + temp.ToString() + ")"
         | ErrorTy(_) ->
             "Error"
         | UnknownTy ->
         | _ ->
             ty
 
+    static member CanDenoteNil (ty : Type) =
+        match ty with
+        | NillableTy(_) 
+        | NilTy ->
+            true
+        | _ ->
+            false
+
 /// (description, rhsType, retTy) for binary operator
 and BinOpTy = string*Type*Type
 

LoveStudio/LuaAnalyzer/Typechecker.fs

     | ErrorField(msg,_) ->
         ()
 
+/// ctxt - the context to reason under
+/// funcTy - the type of the value being called
+/// actuals - the actual arguments supplied to the call
+/// actualTypes - the types of the actual arguments supplied to the call
+/// rng - the range of the call, used in case typechecking errors are generated
+///
+/// If funcTy is an OverloadTy, return the first overload which has formals
+/// which match the supplied actuals. If none match, return UnknownTy and generate
+/// an error. Otherwise, return funcTy.
+let funcTyFromCall (ctxt : Context) 
+                   (funcTy : Type) 
+                   (actuals : List<TypedExpr>) 
+                   (actualTypes : List<Type>)
+                   (rng : Range) 
+                   : Type = 
+
+    Contract.Ensures(
+        match Contract.Result<Type>() with
+        | OverloadTy(_) -> false
+        | _ -> true
+    )
+
+    match funcTy with
+    | OverloadTy(overloads) ->
+        let overloadMatches (ty : Type) =
+            match ty with
+            | FunctionTy(desc,formals,rets,isMethod,loc) ->
+                if actuals.Length > formals.Length then
+                    false
+                else
+                    let actuals =
+                        if actuals.Length > formals.Length then
+                            actuals
+                        else
+                            padList actuals (Nil rng) formals.Length
+
+                    let actualMatchesFormal (actual : TypedExpr) (formalTy : Type) =
+                        let actualTy,_ = typeCheckExpr ctxt actual
+                        fst (Type.IsSubtypeOf ctxt.tenv actualTy formalTy)
+
+                    List.forall2 actualMatchesFormal actuals (List.map (fun (_,_,z) -> z) formals)
+            | _ ->
+                false
+
+        match List.tryFind overloadMatches overloads with
+        | Some(overload) ->
+            overload
+        | None ->
+            if ctxt.trackErrors then
+                addError
+                    !currentFileName
+                    ("argument types " + actualTypes.ToString() + " matches none of the overloads " + overloads.ToString())
+                    rng
+                             
+            UnknownTy
+    | _ ->
+        funcTy
+
 let checkListElement (ctxt : Context) (expectedTy : Type) (field : TypedConstructorField) =
     let fieldTy,rng = 
         match field with
             UnknownTy, None     
     | CallExpr(func,actuals,rng) ->
         let actualTypes = List.map (fun x -> fst (typeCheckExpr ctxt.IsNotLeftExpr x)) actuals
-
-        //returns the input for function types and the call metamethod for record types
         let funcTy = Type.Coerce tenv (fst (typeCheckExpr ctxt.IsNotLeftExpr func))
-
-        // If this is an Overload type, we need to find some overload which
-        // matches the actuals. If multiple overloads match, we choose an
-        // arbitrary one. Anything that goes wrong would then be the fault
-        // of the API designer.
-        let funcTy = 
-            match funcTy with
-            | OverloadTy(overloads) ->
-                let overloadMatches (ty : Type) =
-                    match ty with
-                    | FunctionTy(desc,formals,rets,isMethod,loc) ->
-                        if actuals.Length > formals.Length then
-                            false
-                        else
-                            let actuals =
-                                if actuals.Length > formals.Length then
-                                    actuals
-                                else
-                                    padList actuals (Nil rng) formals.Length
-
-                            let actualMatchesFormal (actual : TypedExpr) (formalTy : Type) =
-                                let actualTy,_ = typeCheckExpr ctxt actual
-                                fst (Type.IsSubtypeOf tenv actualTy formalTy)
-
-                            List.forall2 actualMatchesFormal actuals (List.map (fun (_,_,z) -> z) formals)
-                    | _ ->
-                        false
-
-                match List.tryFind overloadMatches overloads with
-                | Some(overload) ->
-                    overload
-                | None ->
-                    if ctxt.trackErrors then
-                        addError
-                            !currentFileName
-                            ("argument types " + actualTypes.ToString() + " matches none of the overloads " + overloads.ToString())
-                            rng
-                             
-                    UnknownTy
-            | _ ->
-                funcTy
+        let funcTy = funcTyFromCall ctxt funcTy actuals actualTypes rng
 
         match funcTy with
         | CallableTy(_,formals,rets,isMethod,loc) ->
             let numOptionals = ref 0
             let thrd (_,_,x) = x
 
-            let isNillable (ty : Type) =
-                match ty with
-                | NillableTy(_) 
-                | NilTy ->
-                    true
-                | _ ->
-                    false
-
-            while (not (!revFormals).IsEmpty) && (isNillable (thrd (!revFormals).Head)) do
+            while (not (!revFormals).IsEmpty) && (Type.CanDenoteNil (thrd (!revFormals).Head)) do
                 revFormals := (!revFormals).Tail
                 numOptionals := !numOptionals + 1
 
                             ("received " + actuals.Length.ToString() + " arguments. Expected between " + minActuals.ToString() + " and " + formals.Length.ToString() + ".")
                             (funcStart,callFin)
             else
-                let actuals =
-                    padList actuals (Nil rng) formals.Length
-
-                let actualTypes =
-                    padList actualTypes NilTy formals.Length
-
+                let actuals = padList actuals (Nil rng) formals.Length
+                let actualTypes = padList actualTypes NilTy formals.Length
                 let triples = List.zip3 actuals actualTypes formals
-                    
                 let checkTriple ((actual,actualTy,(_,_,formalTy)) : TypedExpr*Type*(string*string*Type)) =
                     ignore (checkType ctxt actual actualTy formalTy)
-
                 List.iter checkTriple triples
 
             if rets.Length > 0 then