diff options
author | Scott Olsen <scg.olsen@gmail.com> | 2022-12-28 01:16:56 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-28 08:16:56 +0100 |
commit | 25f50c92a57cc91b6cb4ec48df658439f936b641 (patch) | |
tree | 15d1d8c0bcc6b34a9449ed802f73b0762dfbb803 | |
parent | 8c5845ea656b80980e8f6b3b39a9477097d6291e (diff) |
chore: make Carp compile w/ GHC 9.2 + stack lts20.0 (#1449)
-rw-r--r-- | src/ArrayTemplates.hs | 406 | ||||
-rw-r--r-- | src/AssignTypes.hs | 10 | ||||
-rw-r--r-- | src/BoxTemplates.hs | 106 | ||||
-rw-r--r-- | src/Concretize.hs | 46 | ||||
-rw-r--r-- | src/Emit.hs | 201 | ||||
-rw-r--r-- | src/Env.hs | 8 | ||||
-rw-r--r-- | src/Eval.hs | 17 | ||||
-rw-r--r-- | src/Expand.hs | 3 | ||||
-rw-r--r-- | src/GenerateConstraints.hs | 198 | ||||
-rw-r--r-- | src/Info.hs | 9 | ||||
-rw-r--r-- | src/InitialTypes.hs | 11 | ||||
-rw-r--r-- | src/Interfaces.hs | 4 | ||||
-rw-r--r-- | src/Memory.hs | 36 | ||||
-rw-r--r-- | src/Meta.hs | 10 | ||||
-rw-r--r-- | src/Obj.hs | 71 | ||||
-rw-r--r-- | src/Parsing.hs | 25 | ||||
-rw-r--r-- | src/Polymorphism.hs | 5 | ||||
-rw-r--r-- | src/Primitives.hs | 19 | ||||
-rw-r--r-- | src/Project.hs | 69 | ||||
-rw-r--r-- | src/Qualify.hs | 42 | ||||
-rw-r--r-- | src/RenderDocs.hs | 13 | ||||
-rw-r--r-- | src/StartingEnv.hs | 9 | ||||
-rw-r--r-- | src/StaticArrayTemplates.hs | 115 | ||||
-rw-r--r-- | src/Sumtypes.hs | 16 | ||||
-rw-r--r-- | src/Template.hs | 12 | ||||
-rw-r--r-- | src/TypeError.hs | 4 |
26 files changed, 855 insertions, 610 deletions
diff --git a/src/ArrayTemplates.hs b/src/ArrayTemplates.hs index 2cf8e325..35fc4065 100644 --- a/src/ArrayTemplates.hs +++ b/src/ArrayTemplates.hs @@ -36,11 +36,15 @@ templateEMap = Template templateType (templateLiteral "Array $NAME(Lambda *f, Array a)") - ( \(FuncTy [_, StructTy (ConcreteNameTy (SymPath [] "Array")) [memberTy]] _ _) -> - handleUnits memberTy + ( \case + (FuncTy [_, StructTy (ConcreteNameTy (SymPath [] "Array")) [memberTy]] _ _) -> + handleUnits memberTy + _ -> error "array templates: emap called on non array" ) - ( \(FuncTy [RefTy t@(FuncTy fArgTys fRetTy _) _, _] _ _) -> - [defineFunctionTypeAlias t, defineFunctionTypeAlias (FuncTy (lambdaEnvTy : fArgTys) fRetTy StaticLifetimeTy)] + ( \case + (FuncTy [RefTy t@(FuncTy fArgTys fRetTy _) _, _] _ _) -> + [defineFunctionTypeAlias t, defineFunctionTypeAlias (FuncTy (lambdaEnvTy : fArgTys) fRetTy StaticLifetimeTy)] + _ -> error "array templates: emap called on non array" ) where elt = "((($a*)a.data)[i])" @@ -96,16 +100,20 @@ templateEFilter = defineTypeParameterizedTemplate templateCreator path t docs Template t (const (toTemplate "Array $NAME(Lambda *predicate, Array a)")) -- Lambda used to be $(Fn [(Ref a)] Bool) - ( \(FuncTy [RefTy (FuncTy [RefTy insideTy _] BoolTy _) _, _] _ _) -> - let deleteCall = insideArrayDeletion typeEnv env insideTy - in ( case insideTy of - UnitTy -> declaration " insertIndex++; /* ignore () member; just increment length. */" deleteCall - _ -> declaration " ((($a*)a.data)[insertIndex++]) = (($a*)a.data)[i];" deleteCall - ) + ( \case + (FuncTy [RefTy (FuncTy [RefTy insideTy _] BoolTy _) _, _] _ _) -> + let deleteCall = insideArrayDeletion typeEnv env insideTy + in ( case insideTy of + UnitTy -> declaration " insertIndex++; /* ignore () member; just increment length. */" deleteCall + _ -> declaration " ((($a*)a.data)[insertIndex++]) = (($a*)a.data)[i];" deleteCall + ) + _ -> error "array tempaltes: efilter called on non-array" ) - ( \(FuncTy [RefTy ft@(FuncTy fArgTys@[RefTy insideType _] BoolTy _) _, _] _ _) -> - [defineFunctionTypeAlias ft, defineFunctionTypeAlias (FuncTy (lambdaEnvTy : fArgTys) BoolTy StaticLifetimeTy)] - ++ depsForDeleteFunc typeEnv env insideType + ( \case + (FuncTy [RefTy ft@(FuncTy fArgTys@[RefTy insideType _] BoolTy _) _, _] _ _) -> + [defineFunctionTypeAlias ft, defineFunctionTypeAlias (FuncTy (lambdaEnvTy : fArgTys) BoolTy StaticLifetimeTy)] + ++ depsForDeleteFunc typeEnv env insideType + _ -> error "array tempaltes: efilter called on non-array" ) templatePushBack :: (String, Binder) @@ -133,17 +141,24 @@ templatePushBack = \_ _ -> Template t - ( \(FuncTy [_, valueTy] _ _) -> - case valueTy of - UnitTy -> toTemplate "Array $NAME(Array a)" - _ -> toTemplate "Array $NAME(Array a, $a value)" + ( \case + (FuncTy [_, valueTy] _ _) -> + case valueTy of + UnitTy -> toTemplate "Array $NAME(Array a)" + _ -> toTemplate "Array $NAME(Array a, $a value)" + _ -> error "array tempaltes: push back called on non array" ) - ( \(FuncTy [_, valueTy] _ _) -> - case valueTy of - UnitTy -> declaration " /* ignore () member */" - _ -> declaration " (($a*)a.data)[a.len - 1] = value;" + ( \case + (FuncTy [_, valueTy] _ _) -> + case valueTy of + UnitTy -> declaration " /* ignore () member */" + _ -> declaration " (($a*)a.data)[a.len - 1] = value;" + _ -> error "array tempaltes: push back called on non array" + ) + ( \case + (FuncTy [_, _] _ _) -> [] + _ -> error "array tempaltes: push back called on non array" ) - (\(FuncTy [_, _] _ _) -> []) templatePushBackBang :: (String, Binder) templatePushBackBang = @@ -169,17 +184,24 @@ templatePushBackBang = \_ _ -> Template t - ( \(FuncTy [_, valueTy] _ _) -> - case valueTy of - UnitTy -> toTemplate "void $NAME(Array *aRef)" - _ -> toTemplate "void $NAME(Array *aRef, $a value)" + ( \case + (FuncTy [_, valueTy] _ _) -> + case valueTy of + UnitTy -> toTemplate "void $NAME(Array *aRef)" + _ -> toTemplate "void $NAME(Array *aRef, $a value)" + _ -> error "array templates pushback bang called on non array" ) - ( \(FuncTy [_, valueTy] _ _) -> - case valueTy of - UnitTy -> declaration " /* ignore () member */" - _ -> declaration " (($a*)aRef->data)[aRef->len - 1] = value;" + ( \case + (FuncTy [_, valueTy] _ _) -> + case valueTy of + UnitTy -> declaration " /* ignore () member */" + _ -> declaration " (($a*)aRef->data)[aRef->len - 1] = value;" + _ -> error "array templates: pushbackbang called on non array" + ) + ( \case + (FuncTy [_, _] _ _) -> [] + _ -> error "array templates: pushbackbang called on non array" ) - (\(FuncTy [_, _] _ _) -> []) templatePopBack :: (String, Binder) templatePopBack = defineTypeParameterizedTemplate templateCreator path t docs @@ -192,23 +214,27 @@ templatePopBack = defineTypeParameterizedTemplate templateCreator path t docs Template t (const (toTemplate "Array $NAME(Array a)")) - ( \(FuncTy [StructTy _ [insideTy]] _ _) -> - let deleteElement = insideArrayDeletion typeEnv env insideTy - in toTemplate - ( unlines - [ "$DECL { ", - " assert(a.len > 0);", - " a.len--;", - " " ++ deleteElement "a.len", - templateShrinkCheck "a", - " return a;", - "}" - ] - ) + ( \case + (FuncTy [StructTy _ [insideTy]] _ _) -> + let deleteElement = insideArrayDeletion typeEnv env insideTy + in toTemplate + ( unlines + [ "$DECL { ", + " assert(a.len > 0);", + " a.len--;", + " " ++ deleteElement "a.len", + templateShrinkCheck "a", + " return a;", + "}" + ] + ) + _ -> error "array templates: pop back called on non array" ) - ( \(FuncTy [arrayType@(StructTy _ [insideTy])] _ _) -> - depsForDeleteFunc typeEnv env arrayType - ++ depsForCopyFunc typeEnv env insideTy + ( \case + (FuncTy [arrayType@(StructTy _ [insideTy])] _ _) -> + depsForDeleteFunc typeEnv env arrayType + ++ depsForCopyFunc typeEnv env insideTy + _ -> error "array templates: pop back called on non array" ) templatePopBackBang :: (String, Binder) @@ -224,27 +250,32 @@ templatePopBackBang = Template t (templateLiteral "$a $NAME(Array *aRef)") - ( \(FuncTy _ returnTy _) -> - case returnTy of - UnitTy -> - multilineTemplate - [ "$DECL { ", - " assert(aRef->len > 0);", - " aRef->len--;", - "}" - ] - _ -> - multilineTemplate - [ "$DECL { ", - " $a ret;", - " assert(aRef->len > 0);", - " ret = (($a*)aRef->data)[aRef->len - 1];", - " aRef->len--;", - " return ret;", - "}" - ] + ( \case + (FuncTy _ returnTy _) -> + case returnTy of + UnitTy -> + multilineTemplate + [ "$DECL { ", + " assert(aRef->len > 0);", + " aRef->len--;", + "}" + ] + _ -> + multilineTemplate + [ "$DECL { ", + " $a ret;", + " assert(aRef->len > 0);", + " ret = (($a*)aRef->data)[aRef->len - 1];", + " aRef->len--;", + " return ret;", + "}" + ] + _ -> error "array tempaltes: pop back bang called on non array" + ) + ( \case + (FuncTy [_] _ _) -> [] + _ -> error "array templates: pop back bang called on non array" ) - (\(FuncTy [_] _ _) -> []) templateNth :: (String, Binder) templateNth = @@ -264,8 +295,9 @@ templateNth = "}" ] ) - ( \(FuncTy [RefTy _ _, _] _ _) -> - [] + ( \case + (FuncTy [RefTy _ _, _] _ _) -> [] + _ -> error "array templates: nth called on non array" ) templateRaw :: (String, Binder) @@ -276,7 +308,10 @@ templateRaw = "returns an array `a` as a raw pointer—useful for interacting with C." (toTemplate "$t* $NAME (Array a)") (toTemplate "$DECL { return a.data; }") - (\(FuncTy [_] _ _) -> []) + ( \case + (FuncTy [_] _ _) -> [] + _ -> error "array templates: raw called on non array" + ) templateUnsafeRaw :: (String, Binder) templateUnsafeRaw = @@ -286,7 +321,10 @@ templateUnsafeRaw = "returns an array `a` as a raw pointer—useful for interacting with C." (toTemplate "$t* $NAME (Array* a)") (toTemplate "$DECL { return a->data; }") - (\(FuncTy [RefTy _ _] _ _) -> []) + ( \case + (FuncTy [RefTy _ _] _ _) -> [] + _ -> error "array templates: unsafe raw called on non array" + ) -- Several setter functions need to ensure the array's member type isn't Unit -- Such setters only run a side effect, so we can even drop bounds checks. @@ -308,29 +346,35 @@ templateAset = defineTypeParameterizedTemplate templateCreator path t docs \typeEnv env -> Template t - ( \(FuncTy [_, _, insideTy] _ _) -> - case insideTy of - UnitTy -> toTemplate "Array $NAME (Array a, int n)" - _ -> toTemplate "Array $NAME (Array a, int n, $t newValue)" + ( \case + (FuncTy [_, _, insideTy] _ _) -> + case insideTy of + UnitTy -> toTemplate "Array $NAME (Array a, int n)" + _ -> toTemplate "Array $NAME (Array a, int n, $t newValue)" + _ -> error "array templates: aset called with non array" ) - ( \(FuncTy [_, _, insideTy] _ _) -> - case insideTy of - -- Just return the same array for unit members. - UnitTy -> toTemplate "$DECL { return a; }" - _ -> - let deleter = insideArrayDeletion typeEnv env insideTy - in multilineTemplate - [ "$DECL {", - " assert(n >= 0);", - " assert(n < a.len);", - deleter "n", - " (($t*)a.data)[n] = newValue;", - " return a;", - "}" - ] + ( \case + (FuncTy [_, _, insideTy] _ _) -> + case insideTy of + -- Just return the same array for unit members. + UnitTy -> toTemplate "$DECL { return a; }" + _ -> + let deleter = insideArrayDeletion typeEnv env insideTy + in multilineTemplate + [ "$DECL {", + " assert(n >= 0);", + " assert(n < a.len);", + deleter "n", + " (($t*)a.data)[n] = newValue;", + " return a;", + "}" + ] + _ -> error "array templates: aset called with non array" ) - ( \(FuncTy [_, _, insideTy] _ _) -> - depsForDeleteFunc typeEnv env insideTy + ( \case + (FuncTy [_, _, insideTy] _ _) -> + depsForDeleteFunc typeEnv env insideTy + _ -> error "array templates: aset called with non array" ) templateAsetBang :: (String, Binder) @@ -343,28 +387,34 @@ templateAsetBang = defineTypeParameterizedTemplate templateCreator path t docs \typeEnv env -> Template t - ( \(FuncTy [_, _, valueType] _ _) -> - case valueType of - UnitTy -> toTemplate "void $NAME (Array *aRef, int n)" - _ -> toTemplate "void $NAME (Array *aRef, int n, $t newValue)" + ( \case + (FuncTy [_, _, valueType] _ _) -> + case valueType of + UnitTy -> toTemplate "void $NAME (Array *aRef, int n)" + _ -> toTemplate "void $NAME (Array *aRef, int n, $t newValue)" + _ -> error "array templates: asetbang called on non array" ) - ( \(FuncTy [_, _, insideTy] _ _) -> - case insideTy of - UnitTy -> unitSetterTemplate - _ -> - let deleter = insideArrayDeletion typeEnv env insideTy - in multilineTemplate - [ "$DECL {", - " Array a = *aRef;", - " assert(n >= 0);", - " assert(n < a.len);", - deleter "n", - " (($t*)a.data)[n] = newValue;", - "}" - ] + ( \case + (FuncTy [_, _, insideTy] _ _) -> + case insideTy of + UnitTy -> unitSetterTemplate + _ -> + let deleter = insideArrayDeletion typeEnv env insideTy + in multilineTemplate + [ "$DECL {", + " Array a = *aRef;", + " assert(n >= 0);", + " assert(n < a.len);", + deleter "n", + " (($t*)a.data)[n] = newValue;", + "}" + ] + _ -> error "array templates: asetbang called on non array" ) - ( \(FuncTy [RefTy arrayType _, _, _] _ _) -> - depsForDeleteFunc typeEnv env arrayType + ( \case + (FuncTy [RefTy arrayType _, _, _] _ _) -> + depsForDeleteFunc typeEnv env arrayType + _ -> error "array templates: asetbang called on non array" ) -- | This function can set uninitialized memory in an array (used together with 'allocate'). @@ -379,23 +429,27 @@ templateAsetUninitializedBang = defineTypeParameterizedTemplate templateCreator \_ _ -> Template t - ( \(FuncTy [_, _, valueType] _ _) -> - case valueType of - UnitTy -> toTemplate "void $NAME (Array *aRef, int n)" - _ -> toTemplate "void $NAME (Array *aRef, int n, $t newValue)" + ( \case + (FuncTy [_, _, valueType] _ _) -> + case valueType of + UnitTy -> toTemplate "void $NAME (Array *aRef, int n)" + _ -> toTemplate "void $NAME (Array *aRef, int n, $t newValue)" + _ -> error "array templates: aset called on non array" ) - ( \(FuncTy [_, _, valueType] _ _) -> - case valueType of - UnitTy -> unitSetterTemplate - _ -> - multilineTemplate - [ "$DECL {", - " Array a = *aRef;", - " assert(n >= 0);", - " assert(n < a.len);", - " (($t*)a.data)[n] = newValue;", - "}" - ] + ( \case + (FuncTy [_, _, valueType] _ _) -> + case valueType of + UnitTy -> unitSetterTemplate + _ -> + multilineTemplate + [ "$DECL {", + " Array a = *aRef;", + " assert(n >= 0);", + " assert(n < a.len);", + " (($t*)a.data)[n] = newValue;", + "}" + ] + _ -> error "array templates: aset called on non array" ) (const []) @@ -411,8 +465,10 @@ templateLength = defineTypeParameterizedTemplate templateCreator path t docs t (const (toTemplate "int $NAME (Array *a)")) (const (toTemplate "$DECL { return (*a).len; }")) - ( \(FuncTy [RefTy arrayType _] _ _) -> - depsForDeleteFunc typeEnv env arrayType + ( \case + (FuncTy [RefTy arrayType _] _ _) -> + depsForDeleteFunc typeEnv env arrayType + _ -> error "array template: length called on non array" ) templateAllocate :: (String, Binder) @@ -426,23 +482,27 @@ templateAllocate = defineTypeParameterizedTemplate templateCreator path t docs Template t (const (toTemplate "Array $NAME (int n)")) - ( \(FuncTy [_] arrayType _) -> - toTemplate $ - unlines - ( [ "$DECL {", - " Array a;", - " a.len = n;", - " a.capacity = n;", - " a.data = CARP_MALLOC(n*sizeof($t));" - ] - ++ initTy arrayType - ++ [ " return a;", - "}" - ] - ) + ( \case + (FuncTy [_] arrayType _) -> + toTemplate $ + unlines + ( [ "$DECL {", + " Array a;", + " a.len = n;", + " a.capacity = n;", + " a.data = CARP_MALLOC(n*sizeof($t));" + ] + ++ initTy arrayType + ++ [ " return a;", + "}" + ] + ) + _ -> error "array template: allocate called on non array" ) - ( \(FuncTy [_] arrayType _) -> - depsForDeleteFunc typeEnv env arrayType + ( \case + (FuncTy [_] arrayType _) -> + depsForDeleteFunc typeEnv env arrayType + _ -> error "array template: allocate called on non array" ) templateDeleteArray :: (String, Binder) @@ -456,13 +516,17 @@ templateDeleteArray = defineTypeParameterizedTemplate templateCreator path t doc Template t (const (toTemplate "void $NAME (Array a)")) - ( \(FuncTy [arrayType] UnitTy _) -> - [TokDecl, TokC "{\n"] - ++ deleteTy typeEnv env arrayType - ++ [TokC "}\n"] + ( \case + (FuncTy [arrayType] UnitTy _) -> + [TokDecl, TokC "{\n"] + ++ deleteTy typeEnv env arrayType + ++ [TokC "}\n"] + _ -> error "array template: delete called with non array" ) - ( \(FuncTy [StructTy (ConcreteNameTy (SymPath [] "Array")) [insideType]] UnitTy _) -> - depsForDeleteFunc typeEnv env insideType + ( \case + (FuncTy [StructTy (ConcreteNameTy (SymPath [] "Array")) [insideType]] UnitTy _) -> + depsForDeleteFunc typeEnv env insideType + _ -> error "array template: delete called with non array" ) deleteTy :: TypeEnv -> Env -> Ty -> [Token] @@ -518,15 +582,17 @@ templateCopyArray = defineTypeParameterizedTemplate templateCreator path t docs Template t (const (toTemplate "Array $NAME (Array* a)")) - ( \(FuncTy [RefTy arrayType _] _ _) -> - [TokDecl, TokC "{\n"] - ++ [TokC " Array copy;\n"] - ++ [TokC " copy.len = a->len;\n"] - ++ [TokC " copy.capacity = a->capacity;\n"] - ++ [TokC " copy.data = CARP_MALLOC(sizeof(", TokTy (VarTy "a") Normal, TokC ") * a->capacity);\n"] - ++ copyTy typeEnv env arrayType - ++ [TokC " return copy;\n"] - ++ [TokC "}\n"] + ( \case + (FuncTy [RefTy arrayType _] _ _) -> + [TokDecl, TokC "{\n"] + ++ [TokC " Array copy;\n"] + ++ [TokC " copy.len = a->len;\n"] + ++ [TokC " copy.capacity = a->capacity;\n"] + ++ [TokC " copy.data = CARP_MALLOC(sizeof(", TokTy (VarTy "a") Normal, TokC ") * a->capacity);\n"] + ++ copyTy typeEnv env arrayType + ++ [TokC " return copy;\n"] + ++ [TokC "}\n"] + err -> error ("CAN'T MATCH: " ++ show err) ) ( \case (FuncTy [RefTy arrayType@(StructTy (ConcreteNameTy (SymPath [] "Array")) [insideType]) _] _ _) -> @@ -576,13 +642,19 @@ templateStrArray = defineTypeParameterizedTemplate templateCreator path t docs Template t (const (toTemplate "String $NAME (Array* a)")) - ( \(FuncTy [RefTy arrayType _] StringTy _) -> - [TokDecl, TokC " {\n"] - ++ strTy typeEnv env arrayType - ++ [TokC "}\n"] + ( \ft -> + case ft of + (FuncTy [RefTy arrayType _] StringTy _) -> + [TokDecl, TokC " {\n"] + ++ strTy typeEnv env arrayType + ++ [TokC "}\n"] + _ -> error "array templates: str called w/ non array" ) - ( \(FuncTy [RefTy (StructTy (ConcreteNameTy (SymPath [] "Array")) [insideType]) _] StringTy _) -> - depsForPrnFunc typeEnv env insideType + ( \ft -> + case ft of + (FuncTy [RefTy (StructTy (ConcreteNameTy (SymPath [] "Array")) [insideType]) _] StringTy _) -> + depsForPrnFunc typeEnv env insideType + _ -> error "array templates: str called w/ non array" ) path = SymPath ["Array"] "str" t = FuncTy [arrayRef] StringTy StaticLifetimeTy diff --git a/src/AssignTypes.hs b/src/AssignTypes.hs index 44b0ea5a..f7bfe9c7 100644 --- a/src/AssignTypes.hs +++ b/src/AssignTypes.hs @@ -56,12 +56,16 @@ isArrayTypeOK _ = True -- | TODO: Only change variables that are machine generated. beautifyTypeVariables :: XObj -> Either TypeError XObj beautifyTypeVariables root = - let Just t = xobjTy root - tys = nub (typeVariablesInOrderOfAppearance t) + let tys = case xobjTy root of + Just t -> nub (typeVariablesInOrderOfAppearance t) + Nothing -> [] mappings = Map.fromList ( zip - (map (\(VarTy name) -> name) tys) + (map go tys) (map (VarTy . (: [])) ['a' ..]) ) in assignTypes mappings root + where + go (VarTy name) = name + go _ = "" -- called with non var type diff --git a/src/BoxTemplates.hs b/src/BoxTemplates.hs index 2ef6803b..d31bd391 100644 --- a/src/BoxTemplates.hs +++ b/src/BoxTemplates.hs @@ -96,12 +96,18 @@ copy = Template t decl - ( \(FuncTy [RefTy (StructTy (ConcreteNameTy (SymPath [] "Box")) [inner]) _] _ _) -> - innerCopy tenv env inner + ( \ft -> + case ft of + (FuncTy [RefTy (StructTy (ConcreteNameTy (SymPath [] "Box")) [inner]) _] _ _) -> + innerCopy tenv env inner + _ -> error "box templates: copy called with non box" ) - ( \(FuncTy [RefTy boxType@(StructTy (ConcreteNameTy (SymPath [] "Box")) [inner]) _] _ _) -> - depsForCopyFunc tenv env inner - ++ depsForDeleteFunc tenv env boxType + ( \ft -> + case ft of + (FuncTy [RefTy boxType@(StructTy (ConcreteNameTy (SymPath [] "Box")) [inner]) _] _ _) -> + depsForCopyFunc tenv env inner + ++ depsForDeleteFunc tenv env boxType + _ -> error "box templates: copy called with non box" ) in defineTypeParameterizedTemplate template path t docs where @@ -138,15 +144,21 @@ delete = Template t decl - ( \(FuncTy [bTy] UnitTy _) -> - multilineTemplate - [ "$DECL {", - " " ++ innerDelete tenv env bTy, - "}" - ] + ( \ft -> + case ft of + (FuncTy [bTy] UnitTy _) -> + multilineTemplate + [ "$DECL {", + " " ++ innerDelete tenv env bTy, + "}" + ] + _ -> error "box templates: delete called with non box" ) - ( \(FuncTy [StructTy (ConcreteNameTy (SymPath [] "Box")) [insideType]] UnitTy _) -> - depsForDeleteFunc tenv env insideType + ( \ft -> + case ft of + (FuncTy [StructTy (ConcreteNameTy (SymPath [] "Box")) [insideType]] UnitTy _) -> + depsForDeleteFunc tenv env insideType + _ -> error "box templates: delete called with non box" ) in defineTypeParameterizedTemplate templateCreator path t docs where @@ -175,21 +187,27 @@ prn = Template t decl - ( \(FuncTy [boxT] StringTy _) -> - multilineTemplate - [ "$DECL {", - " if(!box){", - " String buffer = CARP_MALLOC(4);", - " sprintf(buffer, \"Nil\");", - " return buffer;", - " }", - innerStr tenv env boxT, - " return buffer;", - "}" - ] + ( \ft -> + case ft of + (FuncTy [boxT] StringTy _) -> + multilineTemplate + [ "$DECL {", + " if(!box){", + " String buffer = CARP_MALLOC(4);", + " sprintf(buffer, \"Nil\");", + " return buffer;", + " }", + innerStr tenv env boxT, + " return buffer;", + "}" + ] + _ -> error "box templates: prn called with non box" ) - ( \(FuncTy [(StructTy (ConcreteNameTy (SymPath [] "Box")) [inner])] StringTy _) -> - depsForPrnFunc tenv env inner + ( \ft -> + case ft of + (FuncTy [(StructTy (ConcreteNameTy (SymPath [] "Box")) [inner])] StringTy _) -> + depsForPrnFunc tenv env inner + _ -> error "box tempaltes: prn called with non box" ) ) in defineTypeParameterizedTemplate templateCreator path t docs @@ -206,21 +224,27 @@ str = Template t (templateLiteral "String $NAME ($t** box)") - ( \(FuncTy [RefTy boxT _] StringTy _) -> - multilineTemplate - [ "$DECL {", - " if(!box){", - " String buffer = CARP_MALLOC(4);", - " sprintf(buffer, \"Nil\");", - " return buffer;", - " }", - innerStr tenv env boxT, - " return buffer;", - "}" - ] + ( \ft -> + case ft of + (FuncTy [RefTy boxT _] StringTy _) -> + multilineTemplate + [ "$DECL {", + " if(!box){", + " String buffer = CARP_MALLOC(4);", + " sprintf(buffer, \"Nil\");", + " return buffer;", + " }", + innerStr tenv env boxT, + " return buffer;", + "}" + ] + _ -> error "box templates: str called with non box ref" ) - ( \(FuncTy [RefTy (StructTy (ConcreteNameTy (SymPath [] "Box")) [inner]) _] StringTy _) -> - depsForPrnFunc tenv env inner + ( \ft -> + case ft of + (FuncTy [RefTy (StructTy (ConcreteNameTy (SymPath [] "Box")) [inner]) _] StringTy _) -> + depsForPrnFunc tenv env inner + _ -> error "box templates: str template called with non box type" ) ) in defineTypeParameterizedTemplate templateCreator path t docs diff --git a/src/Concretize.hs b/src/Concretize.hs index bd2ead10..b3127203 100644 --- a/src/Concretize.hs +++ b/src/Concretize.hs @@ -126,9 +126,12 @@ envWithFunctionArgs :: Env -> [XObj] -> Either EnvironmentError Env envWithFunctionArgs env arr = let functionEnv = Env Map.empty (Just env) Nothing Set.empty InternalEnv (envFunctionNestingLevel env) in foldM - (\e arg@(XObj (Sym path _) _ _) -> insertX e path arg) + go functionEnv arr + where + go e arg@(XObj (Sym path _) _ _) = insertX e path arg + go e _ = pure e -- | Concretely type a function definition. -- @@ -255,7 +258,7 @@ mkLambda visited allowAmbig _ tenv env root@(ListPat (FnPat fn arr@(ArrPat args) -- Its name will contain the name of the (normal, non-lambda) function it's contained within, -- plus the identifier of the particular s-expression that defines the lambda. SymPath spath name = (last visited) - Just funcTy = xobjTy root + funcTy = fromMaybe (error "concretize: can't concretize a lambda without type") $ xobjTy root lambdaPath = SymPath spath ("_Lambda_" ++ lambdaToCName name (envFunctionNestingLevel env) ++ "_" ++ show (maybe 0 infoIdentifier (xobjInfo root)) ++ "_env") lambdaNameSymbol = XObj (Sym lambdaPath Symbol) (Just dummyInfo) Nothing -- Anonymous functions bound to a let name might call themselves. These recursive instances will have already been qualified as LookupRecursive symbols. @@ -286,8 +289,11 @@ mkLambda visited allowAmbig _ tenv env root@(ListPat (FnPat fn arr@(ArrPat args) -- (if it captures at least one variable) structMemberPairs = concatMap - ( \(XObj (Sym path _) _ (Just symTy)) -> - [XObj (Sym path Symbol) Nothing Nothing, reify symTy] + ( \x -> + case x of + (XObj (Sym path _) _ (Just symTy)) -> + [XObj (Sym path Symbol) Nothing Nothing, reify symTy] + _ -> error "concretize: struct member pair is a non symbol" ) capturedVars environmentStructTy = StructTy (ConcreteNameTy tyPath) [] @@ -365,7 +371,7 @@ visitSymbol visited allowAmbig tenv env xobj@(SymPat path mode) = Right (foundEnv, binder) | envIsExternal foundEnv -> let theXObj = binderXObj binder - Just theType = xobjTy theXObj + theType = fromMaybe (error "concretize: can't concretize a symbol without a type") $ xobjTy theXObj typeOfVisited = fromMaybe (error ("Missing type on " ++ show xobj ++ " at " ++ prettyInfoFromXObj xobj ++ " when looking up path " ++ show path)) (xobjTy xobj) in if --(trace $ "CHECKING " ++ getName xobj ++ " : " ++ show theType ++ " with visited type " ++ show typeOfVisited ++ " and visited definitions: " ++ show visitedDefinitions) $ (isTypeGeneric theType && not (isTypeGeneric typeOfVisited)) @@ -389,7 +395,7 @@ visitMultiSym visited allowAmbig tenv env xobj@(MultiSymPat name paths) = [x] -> go x _ -> pure (Right xobj) where - Just actualType = xobjTy xobj + actualType = fromMaybe (error "concretize: can't concretize a multisym without a type") $ xobjTy xobj tys = map (typeFromPath env) paths modes = map (modeFromPath env) paths tysToPathsDict = zip tys paths @@ -417,19 +423,19 @@ visitInterfaceSym :: [SymPath] -> Bool -> TypeEnv -> Env -> XObj -> State [XObj] visitInterfaceSym visited allowAmbig tenv env xobj@(InterfaceSymPat name) = either (pure . const (Left (CannotConcretize xobj))) go (getTypeBinder tenv name) where - Just actualType = (xobjTy xobj) + actualType = fromMaybe (error "concretize: can't concretize an interface without type") $ (xobjTy xobj) go :: Binder -> State [XObj] (Either TypeError XObj) go (Binder _ (ListPat (InterfacePat _ paths))) = let tys = map (typeFromPath env) paths modes = map (modeFromPath env) paths tysModesPathsDict = zip3 tys modes paths in case filter (\(t, _, p) -> matchingSignature actualType (t, p)) tysModesPathsDict of - [] -> pure $ if allowAmbig then Right xobj else Left (NoMatchingSignature xobj name actualType (map (\(t, _, p) -> (t,p)) tysModesPathsDict)) + [] -> pure $ if allowAmbig then Right xobj else Left (NoMatchingSignature xobj name actualType (map (\(t, _, p) -> (t, p)) tysModesPathsDict)) [x] -> updateSym x - xs -> case filter (\(t,_,_) -> typeEqIgnoreLifetimes actualType t) xs of + xs -> case filter (\(t, _, _) -> typeEqIgnoreLifetimes actualType t) xs of [] -> pure (Right xobj) -- No exact match of types [y] -> updateSym y - ps -> pure (Left (SeveralExactMatches xobj name actualType (map (\(t, _, p) -> (t,p)) ps))) + ps -> pure (Left (SeveralExactMatches xobj name actualType (map (\(t, _, p) -> (t, p)) ps))) go _ = pure (Left (CannotConcretize xobj)) -- TODO: Should we also check for allowAmbig here? updateSym (_, mode, path) = if isTypeGeneric actualType then pure (Right xobj) else replace mode path @@ -577,7 +583,7 @@ renameGenericTypeSymbolsOnSum varpairs x@(XObj (Lst (caseNm : [a@(XObj (Arr arr) mapp = Map.fromList varpairs replacer mem@(XObj (Sym (SymPath [] name) _) _ _) = - let Just perhapsTyVar = xobjToTy mem + let perhapsTyVar = fromMaybe (error "concretize: can't replace generics on sum without type") $ xobjToTy mem in if isFullyGenericType perhapsTyVar then case Map.lookup (VarTy name) mapp of Just new -> reify new @@ -592,7 +598,7 @@ renameGenericTypeSymbolsOnProduct vars members = concatMap (\(var, (v, t)) -> [v, rename var t]) (zip vars (pairwise members)) where rename var mem = - let Just perhapsTyVar = xobjToTy mem + let perhapsTyVar = fromMaybe (error "concretize: can't replace generics on product without type") $ xobjToTy mem in if isFullyGenericType perhapsTyVar then reify var else mem @@ -606,8 +612,12 @@ instantiateGenericStructType typeEnv env originalStructTy@(StructTy _ _) generic where fake1 = XObj (Sym (SymPath [] "a") Symbol) Nothing Nothing fake2 = XObj (Sym (SymPath [] "b") Symbol) Nothing Nothing - XObj (Arr memberXObjs) _ _ = head membersXObjs - rename@(StructTy _ renamedOrig) = evalState (renameVarTys originalStructTy) 0 + memberXObjs = case head membersXObjs of + XObj (Arr xs) _ _ -> xs + _ -> error "can't instantiate non array member objects" + (rename, renamedOrig) = case evalState (renameVarTys originalStructTy) 0 of + (StructTy n ro) -> ((StructTy n ro), ro) + _ -> error "concretize: can't instantiate a non struct type" solution = solve [Constraint originalStructTy genericStructTy fake1 fake2 fake1 OrdMultiSym] go mappings = do mappings' <- replaceLeft (FailedToInstantiateGenericType originalStructTy) (solve [Constraint rename genericStructTy fake1 fake2 fake1 OrdMultiSym]) @@ -643,7 +653,9 @@ instantiateGenericSumtype :: TypeEnv -> Env -> Ty -> Ty -> [XObj] -> Either Type instantiateGenericSumtype typeEnv env originalStructTy@(StructTy _ originalTyVars) genericStructTy cases = let fake1 = XObj (Sym (SymPath [] "a") Symbol) Nothing Nothing fake2 = XObj (Sym (SymPath [] "b") Symbol) Nothing Nothing - rename@(StructTy _ renamedOrig) = evalState (renameVarTys originalStructTy) 0 + (rename, renamedOrig) = case evalState (renameVarTys originalStructTy) 0 of + (StructTy n ro) -> ((StructTy n ro), ro) + _ -> error "concretize: can't instantiate non struct type" nameFixedCases = map (renameGenericTypeSymbolsOnSum (zip originalTyVars renamedOrig)) cases fixLeft l = replaceLeft (FailedToInstantiateGenericType originalStructTy) l in do @@ -692,7 +704,7 @@ replaceGenericTypeSymbolsOnMembers mappings memberXObjs = replaceGenericTypeSymbols :: Map.Map String Ty -> XObj -> XObj replaceGenericTypeSymbols mappings xobj@(XObj (Sym (SymPath _ name) _) _ _) = - let Just perhapsTyVar = xobjToTy xobj + let perhapsTyVar = fromMaybe (error "concretize: can't replace generics on xobj with no type") $ xobjToTy xobj in if isFullyGenericType perhapsTyVar then maybe xobj reify (Map.lookup name mappings) else xobj @@ -758,7 +770,7 @@ modeFromPath env p = concretizeDefinition :: Bool -> TypeEnv -> Env -> [SymPath] -> XObj -> Ty -> Either TypeError (XObj, [XObj]) concretizeDefinition allowAmbiguity typeEnv globalEnv visitedDefinitions definition concreteType = let SymPath pathStrings name = getPath definition - Just polyType = xobjTy definition + polyType = fromMaybe (error "concretize: definition without a type") $ xobjTy definition suffix = polymorphicSuffix polyType concreteType newPath = SymPath pathStrings (name ++ suffix) in case definition of diff --git a/src/Emit.hs b/src/Emit.hs index 814bcadd..a41c85d3 100644 --- a/src/Emit.hs +++ b/src/Emit.hs @@ -204,7 +204,7 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo visitSymbol _ (XObj (Sym _ (LookupGlobalOverride overrideWithName)) _ _) = pure overrideWithName visitSymbol indent xobj@(XObj sym@(Sym path lookupMode) (Just i) ty) = - let Just t = ty + let t = fromMaybe (error "emit: symbol has no type") $ ty in if isTypeGeneric t then error @@ -237,7 +237,9 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo _ -> do let innerIndent = indent + indentAmount - Just (FuncTy _ retTy _) = ty + retTy = case ty of + Just (FuncTy _ rt _) -> rt + _ -> error "emit: defn has no return type" defnDecl = defnToDeclaration meta path argList retTy isMain = name == "main" appendToSrc (defnDecl ++ " {\n") @@ -255,7 +257,7 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo do let retVar = freshVar info capturedVars = Set.toList set - Just callback = name + callback = fromMaybe (SymPath [] "") name callbackMangled = pathToC callback needEnv = not (null capturedVars) lambdaEnvTypeName = (SymPath [] (callbackMangled ++ "_ty")) -- The name of the struct is the callback name with suffix '_ty'. @@ -277,17 +279,20 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo ++ "));\n" ) mapM_ - ( \(XObj (Sym path lookupMode) _ _) -> - appendToSrc - ( addIndent indent ++ lambdaEnvName ++ "->" - ++ pathToC path - ++ " = " - ++ ( case lookupMode of - LookupLocal (Capture _) -> "_env->" ++ pathToC path - _ -> pathToC path - ) - ++ ";\n" - ) + ( \xobj -> + case xobj of + (XObj (Sym path lookupMode) _ _) -> + appendToSrc + ( addIndent indent ++ lambdaEnvName ++ "->" + ++ pathToC path + ++ " = " + ++ ( case lookupMode of + LookupLocal (Capture _) -> "_env->" ++ pathToC path + _ -> pathToC path + ) + ++ ";\n" + ) + _ -> appendToSrc "" ) (remove (isUnit . forceTy) capturedVars) appendToSrc (addIndent indent ++ "Lambda " ++ retVar ++ " = {\n") @@ -317,7 +322,7 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo [XObj Let _ _, XObj (Arr bindings) _ _, body] -> let indent' = indent + indentAmount in do - let Just bodyTy = xobjTy body + let bodyTy = fromMaybe (error "emit: let body has no type") $ xobjTy body isNotVoid = bodyTy /= UnitTy letBodyRet = freshVar info when isNotVoid $ -- Must be declared outside the scope @@ -326,7 +331,7 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo let letBindingToC (XObj (Sym (SymPath _ symName) _) _ _) expr = do ret <- visit indent' expr - let Just bindingTy = xobjTy expr + let bindingTy = fromMaybe (error "emit: let binding value has no type") $ xobjTy expr unless (isUnit bindingTy) $ appendToSrc (addIndent indent' ++ tyToCLambdaFix bindingTy ++ " " ++ mangle symName ++ " = " ++ ret ++ ";\n") letBindingToC _ _ = error "Invalid binding." @@ -344,18 +349,18 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo let isNotVoid = xobjTy ifTrue /= Just UnitTy ifRetVar = freshVar info when isNotVoid $ - let Just ifT = xobjTy ifTrue + let ifT = fromMaybe (error "emit: if true branch has no type") $ xobjTy ifTrue in appendToSrc (addIndent indent ++ tyToCLambdaFix ifT ++ " " ++ ifRetVar ++ ";\n") exprVar <- visit indent expr appendToSrc (addIndent indent ++ "if (" ++ exprVar ++ ") {\n") trueVar <- visit indent' ifTrue - let Just ifTrueInfo = xobjInfo ifTrue + let ifTrueInfo = infoOrUnknown $ xobjInfo ifTrue delete indent' ifTrueInfo when isNotVoid $ appendToSrc (addIndent indent' ++ ifRetVar ++ " = " ++ trueVar ++ ";\n") appendToSrc (addIndent indent ++ "} else {\n") falseVar <- visit indent' ifFalse - let Just ifFalseInfo = xobjInfo ifFalse + let ifFalseInfo = infoOrUnknown $ xobjInfo ifFalse delete indent' ifFalseInfo when isNotVoid $ appendToSrc (addIndent indent' ++ ifRetVar ++ " = " ++ falseVar ++ ";\n") @@ -384,7 +389,7 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo tempVarToAvoidClash = freshVar exprInfo ++ "_temp" emitCaseMatcher :: (String, String) -> String -> XObj -> Integer -> State EmitterState () emitCaseMatcher (periodOrArrow, ampersandOrNot) caseName (XObj (Sym path _) _ t) index = - let Just tt = t + let tt = fromMaybe (error "emit: case matcher has no type") $ t in appendToSrc ( addIndent indent' ++ tyToCLambdaFix tt ++ " " ++ pathToC path ++ " = " ++ ampersandOrNot @@ -446,13 +451,13 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo caseExprRetVal <- visit indent' caseExpr when isNotVoid $ appendToSrc (addIndent indent' ++ retVar ++ " = " ++ caseExprRetVal ++ ";\n") - let Just caseLhsInfo' = caseLhsInfo + let caseLhsInfo' = infoOrUnknown caseLhsInfo delete indent' caseLhsInfo' appendToSrc (addIndent indent ++ "}\n") in do exprVar <- visit indent expr when isNotVoid $ - let Just t = ty + let t = fromMaybe (error "emit: match expression has no type") $ ty in appendToSrc (addIndent indent ++ tyToCLambdaFix t ++ " " ++ retVar ++ ";\n") zipWithM_ (emitCase exprVar) (True : repeat False) (pairwise rest) appendToSrc (addIndent indent ++ "else UNHANDLED(\"" ++ takeFileName (infoFile info) ++ "\", " ++ show (infoLine info) ++ ");\n") @@ -462,9 +467,9 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo -- While [XObj While _ _, expr, body] -> let indent' = indent + indentAmount - Just exprTy = xobjTy expr + exprTy = fromMaybe (error "emit: called on while expression has no type") $ xobjTy expr conditionVar = freshVar info - Just exprInfo = xobjInfo expr + exprInfo = infoOrUnknown $ xobjInfo expr in do exprRetVar <- visitWhileExpression indent appendToSrc (addIndent indent ++ tyToCLambdaFix exprTy ++ " " ++ conditionVar ++ " = " ++ exprRetVar ++ ";\n") @@ -496,7 +501,7 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo let lastExpr = last expressions retVar = freshVar info mapM_ (visit indent) (init expressions) - let (Just lastTy) = xobjTy lastExpr + let lastTy = fromMaybe (error "emit: final expression in do has no type") $ xobjTy lastExpr if lastTy == UnitTy then do _ <- visit indent lastExpr @@ -514,7 +519,7 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo (XObj (Lst (XObj (Sym (SymPath _ "copy") _) _ _ : (XObj (Sym sym _) _ _) : _)) _ _) -> "*" ++ pathToC sym (XObj (Sym sym _) _ _) -> pathToC sym _ -> error (show (CannotSet variable)) - Just varInfo = xobjInfo variable + varInfo = infoOrUnknown $ xobjInfo variable --appendToSrc (addIndent indent ++ "// " ++ show (length (infoDelete varInfo)) ++ " deleters for " ++ properVariableName ++ ":\n") delete indent varInfo appendToSrc @@ -530,7 +535,7 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo [XObj The _ _, _, value] -> do var <- visit indent value - let Just t = ty + let t = fromMaybe (error "emit: called emit on the with no type") ty fresh = mangle (freshVar info) unless (isUnit t) @@ -540,7 +545,9 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo [XObj Ref _ _, value] -> do var <- visit indent value - let Just t = ty + let t = case ty of + Just typ -> typ + _ -> error "emit: called emit on ref with no type" fresh = mangle (freshVar info) case t of (RefTy UnitTy _) -> appendToSrc "" @@ -548,7 +555,9 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo if isNumericLiteral value then do let literal = freshVar info ++ "_lit" - Just literalTy = xobjTy value + literalTy = case xobjTy value of + Just typ -> typ + _ -> error "called emit on ref without value type" appendToSrc (addIndent indent ++ "static " ++ tyToCLambdaFix literalTy ++ " " ++ literal ++ " = " ++ var ++ ";\n") appendToSrc (addIndent indent ++ tyToCLambdaFix t ++ " " ++ fresh ++ " = &" ++ literal ++ "; // ref\n") else appendToSrc (addIndent indent ++ tyToCLambdaFix t ++ " " ++ fresh ++ " = &" ++ var ++ "; // ref\n") @@ -573,10 +582,13 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo pure "" _ -> do - let Just t = ty - appendToSrc (templateToC template path t) - pure "" - -- Alias + case ty of + Just t -> + do + appendToSrc (templateToC template path t) + pure "" + _ -> pure "" -- called with no type + -- Alias XObj (Defalias _) _ _ : _ -> pure "" -- External @@ -612,10 +624,9 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo func@(XObj (Sym _ (LookupGlobalOverride overriddenName)) _ _) : args -> do argListAsC <- createArgList indent True args -- The 'True' means "unwrap lambdas" which is always the case for functions with overriden names (they are external) - let funcTy = case xobjTy func of - Just actualType -> actualType + let retTy = case xobjTy func of + Just (FuncTy _ rt _) -> rt _ -> error ("No type on func " ++ show func) - FuncTy _ retTy _ = funcTy callFunction = overriddenName ++ "(" ++ argListAsC ++ ");\n" if isUnit retTy then do @@ -629,7 +640,9 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo func@(XObj (Sym path (LookupGlobal mode AFunction)) _ _) : args -> do argListAsC <- createArgList indent (mode == ExternalCode) args - let Just (FuncTy _ retTy _) = xobjTy func + let retTy = case xobjTy func of + Just (FuncTy _ rt _) -> rt + _ -> error "failed to emit function application for non-function type." funcToCall = pathToC path if isUnit retTy then do @@ -647,10 +660,9 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo XObj (Sym _ (LookupGlobal ExternalCode _)) _ _ -> True _ -> False argListAsC <- createArgList indent unwrapLambdas args - let funcTy = case xobjTy func of - Just actualType -> actualType + let (argTys, retTy) = case xobjTy func of + Just (FuncTy at rt _) -> (at, rt) _ -> error ("No type on func " ++ show func) - FuncTy argTys retTy _ = funcTy voidless = remove isUnit argTys castToFn = if unwrapLambdas @@ -700,23 +712,26 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo do let arrayVar = freshVar i len = length xobjs - Just (StructTy (ConcreteNameTy (SymPath [] "Array")) [innerTy]) = t - appendToSrc - ( addIndent indent ++ "Array " ++ arrayVar - ++ " = { .len = " - ++ show len - ++ "," - ++ " .capacity = " - ++ show len - ++ "," - ++ " .data = CARP_MALLOC(sizeof(" - ++ tyToCLambdaFix innerTy - ++ ") * " - ++ show len - ++ ") };\n" - ) - zipWithM_ (visitArrayElement indent arrayVar innerTy) [0 ..] xobjs - pure arrayVar + case t of + Just (StructTy (ConcreteNameTy (SymPath [] "Array")) [innerTy]) -> + do + appendToSrc + ( addIndent indent ++ "Array " ++ arrayVar + ++ " = { .len = " + ++ show len + ++ "," + ++ " .capacity = " + ++ show len + ++ "," + ++ " .data = CARP_MALLOC(sizeof(" + ++ tyToCLambdaFix innerTy + ++ ") * " + ++ show len + ++ ") };\n" + ) + zipWithM_ (visitArrayElement indent arrayVar innerTy) [0 ..] xobjs + pure arrayVar + _ -> pure "" -- called with non-array type visitArray _ _ = error "Must visit array!" visitArrayElement :: Int -> String -> Ty -> Int -> XObj -> State EmitterState () visitArrayElement indent arrayVar innerTy index xobj = @@ -741,21 +756,24 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo retVar = arrayVar ++ "_retref" arrayDataVar = arrayVar ++ "_data" len = length xobjs - Just tt@(RefTy (StructTy (ConcreteNameTy (SymPath [] "StaticArray")) [innerTy]) _) = t - appendToSrc (addIndent indent ++ tyToCLambdaFix innerTy ++ " " ++ arrayDataVar ++ "[" ++ show len ++ "];\n") - appendToSrc - ( addIndent indent ++ "Array " ++ arrayVar - ++ " = { .len = " - ++ show len - ++ "," - ++ " /* .capacity = DOES NOT MATTER, STACK ALLOCATED ARRAY, */" - ++ " .data = " - ++ arrayDataVar - ++ " };\n" - ) - zipWithM_ (visitStaticArrayElement indent arrayDataVar innerTy) [0 ..] xobjs - appendToSrc (addIndent indent ++ tyToCLambdaFix tt ++ " " ++ retVar ++ " = &" ++ arrayVar ++ ";\n") - pure retVar + case t of + Just tt@(RefTy (StructTy (ConcreteNameTy (SymPath [] "StaticArray")) [innerTy]) _) -> + do + appendToSrc (addIndent indent ++ tyToCLambdaFix innerTy ++ " " ++ arrayDataVar ++ "[" ++ show len ++ "];\n") + appendToSrc + ( addIndent indent ++ "Array " ++ arrayVar + ++ " = { .len = " + ++ show len + ++ "," + ++ " /* .capacity = DOES NOT MATTER, STACK ALLOCATED ARRAY, */" + ++ " .data = " + ++ arrayDataVar + ++ " };\n" + ) + zipWithM_ (visitStaticArrayElement indent arrayDataVar innerTy) [0 ..] xobjs + appendToSrc (addIndent indent ++ tyToCLambdaFix tt ++ " " ++ retVar ++ " = &" ++ arrayVar ++ ";\n") + pure retVar + _ -> pure "" -- called with non-array type visitStaticArray _ _ = error "Must visit static array!" visitStaticArrayElement :: Int -> String -> Ty -> Int -> XObj -> State EmitterState () visitStaticArrayElement indent arrayDataVar _ index xobj = @@ -785,7 +803,9 @@ delete indent i = mapM_ deleterToC (infoDelete i) defnToDeclaration :: MetaData -> SymPath -> [XObj] -> Ty -> String defnToDeclaration meta path@(SymPath _ name) argList retTy = let override = Meta.getString (Meta.getCompilerKey Meta.CNAME) meta - (XObj (Lst annotations) _ _) = fromMaybe emptyList (Meta.get "annotations" meta) + annotations = case fromMaybe emptyList (Meta.get "annotations" meta) of + (XObj (Lst xs) _ _) -> xs + _ -> [] annotationsStr = joinWith " " (map strToC annotations) sep = if not (null annotationsStr) then " " else "" fullname = if (null override) then (pathToC path) else override @@ -895,15 +915,18 @@ toDeclaration :: Binder -> String toDeclaration (Binder meta xobj@(XObj (Lst xobjs) _ ty)) = case xobjs of [XObj (Defn _) _ _, XObj (Sym path _) _ _, XObj (Arr argList) _ _, _] -> - let (Just (FuncTy _ retTy _)) = ty - in defnToDeclaration meta path argList retTy ++ ";\n" + case ty of + (Just (FuncTy _ retTy _)) -> defnToDeclaration meta path argList retTy ++ ";\n" + _ -> "" -- called with non-function type, emit nothing. [XObj Def _ _, XObj (Sym path _) _ _, _] -> - let Just t = ty - cname = (Meta.getString (Meta.getCompilerKey Meta.CNAME) meta) - fullname = if (null cname) then pathToC path else cname - in if (isUnit t) - then "" - else tyToCLambdaFix t ++ " " ++ fullname ++ ";\n" + case ty of + Just t -> + let cname = (Meta.getString (Meta.getCompilerKey Meta.CNAME) meta) + fullname = if (null cname) then pathToC path else cname + in if (isUnit t) + then "" + else tyToCLambdaFix t ++ " " ++ fullname ++ ";\n" + _ -> "" -- called with no type, emit nothing. XObj (Deftype t) _ _ : XObj (Sym path _) _ _ : rest -> defStructToDeclaration t path rest XObj (DefSumtype t) _ _ : XObj (Sym _ _) _ _ : rest -> @@ -917,8 +940,9 @@ toDeclaration (Binder meta xobj@(XObj (Lst xobjs) _ ty)) = XObj DefDynamic _ _ : _ -> "" [XObj (Instantiate template) _ _, XObj (Sym path _) _ _] -> - let Just t = ty - in templateToDeclaration template path t + case ty of + Just t -> templateToDeclaration template path t + _ -> "" -- called with no type, emit nothing. [XObj (Defalias aliasTy) _ _, XObj (Sym path _) _ _] -> defaliasToDeclaration aliasTy path [XObj (Interface _ _) _ _, _] -> @@ -1015,14 +1039,9 @@ globalsToC globalEnv = typeEnvToDeclarations :: TypeEnv -> Env -> Either ToCError String typeEnvToDeclarations typeEnv global = let -- We need to carry the type environment to pass the correct environment on the binderToDeclaration call. - addEnvToScore tyE = (sortDeclarationBinders tyE global (map snd (Map.toList (binders tyE)))) bindersWithScore = (addEnvToScore typeEnv) mods = (findModules global) - folder = - ( \sorted (XObj (Mod e t) _ _) -> - sorted ++ (foldl folder (addEnvToScore t) (findModules e)) - ) - allScoredBinders = sortOn fst (foldl folder bindersWithScore mods) + allScoredBinders = sortOn fst (foldl go bindersWithScore mods) in do okDecls <- mapM @@ -1033,6 +1052,10 @@ typeEnvToDeclarations typeEnv global = ) allScoredBinders pure (concat okDecls) + where + addEnvToScore tyE = (sortDeclarationBinders tyE global (map snd (Map.toList (binders tyE)))) + go sorted (XObj (Mod e t) _ _) = sorted ++ (foldl go (addEnvToScore t) (findModules e)) + go xs _ = xs envToDeclarations :: TypeEnv -> Env -> Either ToCError String envToDeclarations typeEnv env = @@ -8,6 +8,7 @@ module Env empty, new, parent, + parentOrEmpty, setParent, nested, recursive, @@ -148,6 +149,13 @@ binders = envBindings . prj parent :: Environment e => e -> Maybe e parent = fmap inj . envParent . prj +-- Attempts to retrieve the parent from an environment. +-- If the environment has no parent, returns the empty environment. +parentOrEmpty :: Environment e => e -> e +parentOrEmpty e = case envParent (prj e) of + Just p -> inj p + Nothing -> empty + -- | Set the parent of an environment. setParent :: Environment e => e -> e -> e setParent e p = inj ((prj e) {envParent = Just (prj p)}) diff --git a/src/Eval.hs b/src/Eval.hs index ac6988fd..660b69a0 100644 --- a/src/Eval.hs +++ b/src/Eval.hs @@ -279,7 +279,7 @@ eval ctx xobj@(XObj o info ty) preference resolver = Left err -> pure (ctx, Left err) Right newCtx -> do (finalCtx, evaledBody) <- eval newCtx body (PreferLocal (map (\(name, _) -> (SymPath [] name)) binds)) ResolveLocal - let Just e = contextInternalEnv finalCtx + let e = fromMaybe E.empty $ contextInternalEnv finalCtx parentEnv = envParent e pure ( replaceInternalEnvMaybe finalCtx parentEnv, @@ -301,7 +301,7 @@ eval ctx xobj@(XObj o info ty) preference resolver = -- (let [f (fn [x] (if (= x 1) x (f (dec x))))] (f 10)) let origin = (contextInternalEnv ctx') recFix = (E.recursive origin (Just "let-rec-env") 0) - Right envWithSelf = if isFn x then E.insertX recFix (SymPath [] n) x else Right recFix + envWithSelf = fromRight recFix $ if isFn x then E.insertX recFix (SymPath [] n) x else Right recFix ctx'' = replaceInternalEnv ctx' envWithSelf (newCtx, res) <- eval ctx'' x preference resolver case res of @@ -350,18 +350,21 @@ eval ctx xobj@(XObj o info ty) preference resolver = evaluateCommand (AppPat (CommandPat (UnaryCommandFunction unary) _ _) [x]) = do (c, evaledArgs) <- foldlM successiveEval (ctx, Right []) [x] case evaledArgs of - Right args -> let [x'] = take 1 args in unary c x' + Right [x'] -> unary c x' Left err -> pure (ctx, Left err) + _ -> error "eval: failed to evaluate command arguments" evaluateCommand (AppPat (CommandPat (BinaryCommandFunction binary) _ _) [x, y]) = do (c, evaledArgs) <- foldlM successiveEval (ctx, Right []) [x, y] case evaledArgs of - Right args -> let [x', y'] = take 2 args in binary c x' y' + Right [x', y'] -> binary c x' y' Left err -> pure (ctx, Left err) + _ -> error "eval: failed to evaluate command arguments" evaluateCommand (AppPat (CommandPat (TernaryCommandFunction ternary) _ _) [x, y, z]) = do (c, evaledArgs) <- foldlM successiveEval (ctx, Right []) [x, y, z] case evaledArgs of - Right args' -> let [x', y', z'] = take 3 args' in ternary c x' y' z' + Right [x', y', z'] -> ternary c x' y' z' Left err -> pure (ctx, Left err) + _ -> error "eval: failed to evaluate command arguments" evaluateCommand (AppPat (CommandPat (VariadicCommandFunction variadic) _ _) args) = do (c, evaledArgs) <- foldlM successiveEval (ctx, Right []) args case evaledArgs of @@ -629,12 +632,12 @@ catcher ctx exception = specialCommandWith :: Context -> XObj -> SymPath -> [XObj] -> IO (Context, Either EvalError XObj) specialCommandWith ctx _ path forms = do - let Just env = contextInternalEnv ctx <|> maybeId (innermostModuleEnv ctx) <|> Just (contextGlobalEnv ctx) + let env = fromMaybe (contextGlobalEnv ctx) $ contextInternalEnv ctx <|> maybeId (innermostModuleEnv ctx) <|> Just (contextGlobalEnv ctx) useThese = envUseModules env env' = env {envUseModules = Set.insert path useThese} ctx' = replaceGlobalEnv ctx env' ctxAfter <- liftIO $ foldM folder ctx' forms - let Just envAfter = contextInternalEnv ctxAfter <|> maybeId (innermostModuleEnv ctxAfter) <|> Just (contextGlobalEnv ctxAfter) + let envAfter = fromMaybe (contextGlobalEnv ctxAfter) (contextInternalEnv ctxAfter <|> maybeId (innermostModuleEnv ctxAfter) <|> Just (contextGlobalEnv ctxAfter)) -- undo ALL use:s made inside the 'with'. ctxAfter' = replaceGlobalEnv ctx (envAfter {envUseModules = useThese}) pure (ctxAfter', dynamicNil) diff --git a/src/Expand.hs b/src/Expand.hs index ef9c58f3..233b4d81 100644 --- a/src/Expand.hs +++ b/src/Expand.hs @@ -2,6 +2,7 @@ module Expand (expandAll, replaceSourceInfoOnXObj) where import Context import Control.Monad.State (State, evalState, get, put) +import Data.Either (fromRight) import Data.Foldable (foldlM) import Env import EvalError @@ -221,7 +222,7 @@ expand eval ctx xobj = if isSpecialSym f then do (ctx', s) <- eval ctx f - let Right sym = s + let sym = fromRight (error "expand: failed to expand special symbol") $ s expand eval ctx' (XObj (Lst (sym : args)) (xobjInfo xobj) (xobjTy xobj)) else do (_, expandedF) <- expand eval ctx f diff --git a/src/GenerateConstraints.hs b/src/GenerateConstraints.hs index 9fe9cbe7..3474423d 100644 --- a/src/GenerateConstraints.hs +++ b/src/GenerateConstraints.hs @@ -21,35 +21,37 @@ genConstraints _ root rootSig = fmap sort (gen root) insideBodyConstraints <- gen body xobjType <- toEither (xobjTy xobj) (DefnMissingType xobj) bodyType <- toEither (xobjTy body) (ExpressionMissingType xobj) - let (FuncTy argTys retTy lifetimeTy) = xobjType - bodyConstr = Constraint retTy bodyType xobj body xobj OrdDefnBody - argConstrs = zipWith3 (\a b aObj -> Constraint a b aObj xobj xobj OrdArg) (List.map forceTy args) argTys args - -- The constraint generated by type signatures, like (sig foo (Fn ...)): - -- This constraint is ignored for any xobj != rootxobj (ie. (fn) let bindings) - sigConstr = - if root == xobj - then case rootSig of - Just (rootSigTy, rootSigXObj) -> [Constraint rootSigTy xobjType rootSigXObj xobj xobj OrdSignatureAnnotation] - Nothing -> [] - else [] - captureList :: [XObj] - captureList = Set.toList captures - capturesConstrs = - catMaybes - ( zipWith - ( \captureTy captureObj -> - case captureTy of - RefTy _ refLt -> - --trace ("Generated constraint between " ++ show lifetimeTy ++ " and " ++ show refLt) $ - Just (Constraint lifetimeTy refLt captureObj xobj xobj OrdCapture) - _ -> - --trace ("Did not generate constraint for captured variable " ++ show captureObj) $ - Nothing + case xobjType of + (FuncTy argTys retTy lifetimeTy) -> + let bodyConstr = Constraint retTy bodyType xobj body xobj OrdDefnBody + argConstrs = zipWith3 (\a b aObj -> Constraint a b aObj xobj xobj OrdArg) (List.map forceTy args) argTys args + -- The constraint generated by type signatures, like (sig foo (Fn ...)): + -- This constraint is ignored for any xobj != rootxobj (ie. (fn) let bindings) + sigConstr = + if root == xobj + then case rootSig of + Just (rootSigTy, rootSigXObj) -> [Constraint rootSigTy xobjType rootSigXObj xobj xobj OrdSignatureAnnotation] + Nothing -> [] + else [] + captureList :: [XObj] + captureList = Set.toList captures + capturesConstrs = + catMaybes + ( zipWith + ( \captureTy captureObj -> + case captureTy of + RefTy _ refLt -> + --trace ("Generated constraint between " ++ show lifetimeTy ++ " and " ++ show refLt) $ + Just (Constraint lifetimeTy refLt captureObj xobj xobj OrdCapture) + _ -> + --trace ("Did not generate constraint for captured variable " ++ show captureObj) $ + Nothing + ) + (List.map forceTy captureList) + captureList ) - (List.map forceTy captureList) - captureList - ) - pure (bodyConstr : argConstrs ++ insideBodyConstraints ++ capturesConstrs ++ sigConstr) + in pure (bodyConstr : argConstrs ++ insideBodyConstraints ++ capturesConstrs ++ sigConstr) + _ -> Left (DefnMissingType xobj) -- TODO: Better error here. gen xobj = case xobjObj xobj of Lst lst -> case lst of @@ -76,21 +78,23 @@ genConstraints _ root rootSig = fmap sort (gen root) insideBodyConstraints <- gen body insideBindingsConstraints <- fmap join (mapM gen bindings) bodyType <- toEither (xobjTy body) (ExpressionMissingType body) - let Just xobjTy' = xobjTy xobj - wholeStatementConstraint = Constraint bodyType xobjTy' body xobj xobj OrdLetBody - bindingsConstraints = - zipWith - ( \(symTy, exprTy) (symObj, exprObj) -> - Constraint symTy exprTy symObj exprObj xobj OrdLetBind - ) - (List.map (forceTy *** forceTy) (pairwise bindings)) - (pairwise bindings) - pure - ( wholeStatementConstraint : - insideBodyConstraints - ++ bindingsConstraints - ++ insideBindingsConstraints - ) + case xobjTy xobj of + Just xobjTy' -> + let wholeStatementConstraint = Constraint bodyType xobjTy' body xobj xobj OrdLetBody + bindingsConstraints = + zipWith + ( \(symTy, exprTy) (symObj, exprObj) -> + Constraint symTy exprTy symObj exprObj xobj OrdLetBind + ) + (List.map (forceTy *** forceTy) (pairwise bindings)) + (pairwise bindings) + in pure + ( wholeStatementConstraint : + insideBodyConstraints + ++ bindingsConstraints + ++ insideBindingsConstraints + ) + Nothing -> Left (ExpressionMissingType xobj) -- If [XObj If _ _, expr, ifTrue, ifFalse] -> do @@ -103,16 +107,18 @@ genConstraints _ root rootSig = fmap sort (gen root) let expected = XObj (Sym (SymPath [] "Condition in if value") Symbol) (xobjInfo expr) (Just BoolTy) let conditionConstraint = Constraint exprType BoolTy expr expected xobj OrdIfCondition sameReturnConstraint = Constraint trueType falseType ifTrue ifFalse xobj OrdIfReturn - Just t = xobjTy xobj - wholeStatementConstraint = Constraint trueType t ifTrue xobj xobj OrdIfWhole - pure - ( conditionConstraint : - sameReturnConstraint : - wholeStatementConstraint : - insideConditionConstraints - ++ insideTrueConstraints - ++ insideFalseConstraints - ) + in case xobjTy xobj of + Just t -> + let wholeStatementConstraint = Constraint trueType t ifTrue xobj xobj OrdIfWhole + in pure + ( conditionConstraint : + sameReturnConstraint : + wholeStatementConstraint : + insideConditionConstraints + ++ insideTrueConstraints + ++ insideFalseConstraints + ) + Nothing -> Left (ExpressionMissingType xobj) -- Match XObj (Match matchMode) _ _ : expr : cases -> do @@ -242,9 +248,11 @@ genConstraints _ root rootSig = fmap sort (gen root) argTys args [0 ..] - Just xobjTy' = xobjTy xobj - retConstraint = Constraint xobjTy' retTy xobj func xobj OrdFuncAppRet - in pure (retConstraint : funcConstraints ++ argConstraints ++ variablesConstraints) + in case xobjTy xobj of + Just xobjTy' -> + let retConstraint = Constraint xobjTy' retTy xobj func xobj OrdFuncAppRet + in pure (retConstraint : funcConstraints ++ argConstraints ++ variablesConstraints) + Nothing -> Left (ExpressionMissingType xobj) funcVarTy@(VarTy _) -> let fabricatedFunctionType = FuncTy (List.map forceTy args) (forceTy xobj) (VarTy "what?!") expected = XObj (Sym (SymPath [] ("Calling '" ++ getName func ++ "'")) Symbol) (xobjInfo func) Nothing @@ -258,42 +266,50 @@ genConstraints _ root rootSig = fmap sort (gen root) [] -> Right [] x : xs -> do insideExprConstraints <- fmap join (mapM gen arr) - let Just headTy = xobjTy x - genObj o n = - XObj - (Sym (SymPath [] ("Whereas the " ++ enumerate n ++ " element in the array is " ++ show (getPath o))) Symbol) - (xobjInfo o) - (xobjTy o) - headObj = - XObj - (Sym (SymPath [] ("I inferred the type of the array from its first element " ++ show (getPath x))) Symbol) - (xobjInfo x) - (Just headTy) - Just (StructTy (ConcreteNameTy (SymPath [] "Array")) [t]) = xobjTy xobj - betweenExprConstraints = zipWith (\o n -> Constraint headTy (forceTy o) headObj (genObj o n) xobj OrdArrBetween) xs [1 ..] - headConstraint = Constraint headTy t headObj (genObj x 1) xobj OrdArrHead - pure (headConstraint : insideExprConstraints ++ betweenExprConstraints) - -- THIS CODE IS VERY MUCH A DUPLICATION OF THE 'ARR' CODE FROM ABOVE: + case xobjTy x of + Nothing -> Left (ExpressionMissingType x) + Just headTy -> + let genObj o n = + XObj + (Sym (SymPath [] ("Whereas the " ++ enumerate n ++ " element in the array is " ++ show (getPath o))) Symbol) + (xobjInfo o) + (xobjTy o) + headObj = + XObj + (Sym (SymPath [] ("I inferred the type of the array from its first element " ++ show (getPath x))) Symbol) + (xobjInfo x) + (Just headTy) + in case xobjTy xobj of + Just (StructTy (ConcreteNameTy (SymPath [] "Array")) [t]) -> + let betweenExprConstraints = zipWith (\o n -> Constraint headTy (forceTy o) headObj (genObj o n) xobj OrdArrBetween) xs [1 ..] + headConstraint = Constraint headTy t headObj (genObj x 1) xobj OrdArrHead + in pure (headConstraint : insideExprConstraints ++ betweenExprConstraints) + _ -> Left (ExpressionMissingType xobj) -- TODO: better error here. + -- THIS CODE IS VERY MUCH A DUPLICATION OF THE 'ARR' CODE FROM ABOVE: (StaticArr arr) -> case arr of [] -> Right [] x : xs -> do insideExprConstraints <- fmap join (mapM gen arr) - let Just headTy = xobjTy x - genObj o n = - XObj - (Sym (SymPath [] ("Whereas the " ++ enumerate n ++ " element in the array is " ++ show (getPath o))) Symbol) - (xobjInfo o) - (xobjTy o) - headObj = - XObj - (Sym (SymPath [] ("I inferred the type of the static array from its first element " ++ show (getPath x))) Symbol) - (xobjInfo x) - (Just headTy) - Just (RefTy (StructTy (ConcreteNameTy (SymPath [] "StaticArray")) [t]) _) = xobjTy xobj - betweenExprConstraints = zipWith (\o n -> Constraint headTy (forceTy o) headObj (genObj o n) xobj OrdArrBetween) xs [1 ..] - headConstraint = Constraint headTy t headObj (genObj x 1) xobj OrdArrHead - pure (headConstraint : insideExprConstraints ++ betweenExprConstraints) + case xobjTy x of + Nothing -> Left (ExpressionMissingType x) + Just headTy -> + let genObj o n = + XObj + (Sym (SymPath [] ("Whereas the " ++ enumerate n ++ " element in the array is " ++ show (getPath o))) Symbol) + (xobjInfo o) + (xobjTy o) + headObj = + XObj + (Sym (SymPath [] ("I inferred the type of the static array from its first element " ++ show (getPath x))) Symbol) + (xobjInfo x) + (Just headTy) + in case xobjTy xobj of + Just (RefTy (StructTy (ConcreteNameTy (SymPath [] "StaticArray")) [t]) _) -> + let betweenExprConstraints = zipWith (\o n -> Constraint headTy (forceTy o) headObj (genObj o n) xobj OrdArrBetween) xs [1 ..] + headConstraint = Constraint headTy t headObj (genObj x 1) xobj OrdArrHead + in pure (headConstraint : insideExprConstraints ++ betweenExprConstraints) + _ -> Left (ExpressionMissingType xobj) -- TODO: Better error here. _ -> Right [] genConstraintsForCaseMatcher :: MatchMode -> XObj -> Either TypeError [Constraint] @@ -317,9 +333,11 @@ genConstraintsForCaseMatcher matchMode = gen (zipWith refWrapper variables argTys) variables [0 ..] - Just xobjTy' = xobjTy xobj - retConstraint = Constraint xobjTy' retTy xobj caseName xobj OrdFuncAppRet - in pure (retConstraint : caseNameConstraints ++ argConstraints ++ variablesConstraints) + in case xobjTy xobj of + Nothing -> Left (ExpressionMissingType xobj) + Just t -> + let retConstraint = Constraint t retTy xobj caseName xobj OrdFuncAppRet + in pure (retConstraint : caseNameConstraints ++ argConstraints ++ variablesConstraints) funcVarTy@(VarTy _) -> let fabricatedFunctionType = FuncTy (List.map forceTy variables) (forceTy xobj) (VarTy "what?!") -- TODO: Fix expected = XObj (Sym (SymPath [] ("Matchin on '" ++ getName caseName ++ "'")) Symbol) (xobjInfo caseName) Nothing diff --git a/src/Info.hs b/src/Info.hs index 45fc1dd4..02993d9a 100644 --- a/src/Info.hs +++ b/src/Info.hs @@ -13,13 +13,14 @@ module Info setDeletersOnInfo, addDeletersToInfo, uniqueDeleter, + infoOrUnknown, ) where +import Data.List (unionBy) import Path (takeFileName) import qualified Set import SymPath -import Data.List (unionBy) -- | Information about where the Obj originated from. data Info = Info @@ -90,6 +91,12 @@ instance Show FilePathPrintLength where dummyInfo :: Info dummyInfo = Info 0 0 "dummy-file" Set.empty (-1) +-- | Attempts to pull the Info out of a Maybe Info, otherwise, returns an Info +-- object representing the fact that Info is missing for the binding. +infoOrUnknown :: Maybe Info -> Info +infoOrUnknown (Just i) = i +infoOrUnknown Nothing = Info 0 0 "unknown" Set.empty (-1) + -- | Returns the line number, column number, and filename associated with an -- Info. getInfo :: Info -> (Int, Int, String) diff --git a/src/InitialTypes.hs b/src/InitialTypes.hs index bd044640..a4d1f251 100644 --- a/src/InitialTypes.hs +++ b/src/InitialTypes.hs @@ -1,6 +1,7 @@ module InitialTypes where import Control.Monad.State +import Data.Either (fromRight) import Env as E import Info import qualified Map @@ -202,7 +203,7 @@ initialTypes typeEnv rootEnv root = evalState (visit rootEnv root) 0 let funcTy = Just (FuncTy argTypes returnType StaticLifetimeTy) typedNameSymbol = nameSymbol {xobjTy = funcTy} -- TODO! After the introduction of 'LookupRecursive' this env shouldn't be needed anymore? (but it is for some reason...) - Right envWithSelf = E.insertX funcScopeEnv (SymPath [] name) typedNameSymbol + envWithSelf = fromRight funcScopeEnv (E.insertX funcScopeEnv (SymPath [] name) typedNameSymbol) visitedBody <- visit envWithSelf body visitedArgs <- mapM (visit envWithSelf) argList pure $ do @@ -220,7 +221,7 @@ initialTypes typeEnv rootEnv root = evalState (visit rootEnv root) 0 lt <- genVarTy let funcTy = Just (FuncTy argTypes returnType lt) typedNameSymbol = XObj (Sym path LookupRecursive) si funcTy - Right envWithSelf = E.insertX funcScopeEnv path typedNameSymbol + envWithSelf = fromRight funcScopeEnv (E.insertX funcScopeEnv path typedNameSymbol) visitedBody <- visit envWithSelf body visitedArgs <- mapM (visit envWithSelf) argList pure $ do @@ -401,8 +402,10 @@ initialTypes typeEnv rootEnv root = evalState (visit rootEnv root) 0 | otherwise -> genVarTy pure $ do okValue <- visitedValue - let Just valueTy = xobjTy okValue - pure (XObj (Lst [refExpr, okValue]) i (Just (RefTy valueTy lt))) + let valueTy = case xobjTy okValue of + Just vt -> (Just (RefTy vt lt)) + Nothing -> Nothing + pure (XObj (Lst [refExpr, okValue]) i valueTy) -- Deref (error!) [XObj Deref _ _, _] -> pure (Left (CantUseDerefOutsideFunctionApplication xobj)) diff --git a/src/Interfaces.hs b/src/Interfaces.hs index 05395e96..7d2dfedc 100644 --- a/src/Interfaces.hs +++ b/src/Interfaces.hs @@ -151,7 +151,9 @@ retroactivelyRegisterInInterface ctx interface = where env = contextGlobalEnv ctx impls = concat (rights (fmap ((flip Env.findImplementations) (getPath (binderXObj interface))) (env : (Env.lookupChildren env)))) - (resultCtx, err) = foldl' (\(Right context, _) binder -> registerInInterface context binder interface) (Right ctx, Nothing) impls + (resultCtx, err) = foldl' go (Right ctx, Nothing) impls + go (Right context, _) binder = registerInInterface context binder interface + go e _ = e -- | Checks whether an interface is implemented for a certain type signature, -- | e.g. Is "delete" implemented for `(Fn [String] ())` ? diff --git a/src/Memory.hs b/src/Memory.hs index 43ed489b..91d37407 100644 --- a/src/Memory.hs +++ b/src/Memory.hs @@ -3,6 +3,7 @@ module Memory (manageMemory) where import Control.Monad.State +import Data.Maybe (fromMaybe) import Forms import Info import Managed @@ -93,7 +94,9 @@ manageMemory typeEnv globalEnv root = whenRight (sequence results) $ do -- We know that we want to add a deleter for the static array here let var = varOfXObj xobj - Just (RefTy t@(StructTy (ConcreteNameTy (SymPath [] "StaticArray")) [_]) _) = xobjTy xobj + t = case xobjTy xobj of + Just (RefTy (StructTy (ConcreteNameTy (SymPath [] "StaticArray")) [vs]) _) -> (StructTy (ConcreteNameTy (SymPath [] "StaticArray")) [vs]) + _ -> error "memory: can't visit static array of non static array type" deleter = case nameOfPolymorphicFunction typeEnv globalEnv (FuncTy [t] UnitTy StaticLifetimeTy) "delete" of Just pathOfDeleteFunc -> ProperDeleter pathOfDeleteFunc (getDropFunc typeEnv globalEnv (xobjInfo xobj) t) var @@ -487,7 +490,7 @@ manage typeEnv globalEnv xobj = Just deleter -> do MemState deleters deps lifetimes <- get let newDeleters = Set.insert deleter deleters - Just t = xobjTy xobj + t = fromMaybe (error "memory: can't manage xobj without type") $ xobjTy xobj newDeps = Set.insert t deps put (MemState newDeleters newDeps lifetimes) Nothing -> pure () @@ -495,7 +498,7 @@ manage typeEnv globalEnv xobj = -- | Remove `xobj` from the set of alive variables, in need of deletion at end of scope. unmanage :: TypeEnv -> Env -> XObj -> State MemState (Either TypeError ()) unmanage typeEnv globalEnv xobj = - let Just t = xobjTy xobj + let t = fromMaybe (error "memory: can't unmange xobj without type") $ xobjTy xobj in if isManaged typeEnv globalEnv t && not (isGlobalFunc xobj) then do MemState deleters deps lifetimes <- get @@ -528,19 +531,20 @@ transferOwnership typeEnv globalEnv from to = -- see issue #597 exclusiveTransferOwnership :: TypeEnv -> Env -> XObj -> XObj -> State MemState (Either TypeError ()) exclusiveTransferOwnership tenv genv from to = - do result <- unmanage tenv genv from - whenRight result $ do - MemState pre deps lts <- get - put (MemState Set.empty deps lts) -- add just this new deleter to the set - manage tenv genv to - MemState post postDeps postLts <- get - put (MemState (uniqueDeleter post pre) postDeps postLts) -- replace any duplicates and union with the prior set - pure (Right ()) + do + result <- unmanage tenv genv from + whenRight result $ do + MemState pre deps lts <- get + put (MemState Set.empty deps lts) -- add just this new deleter to the set + manage tenv genv to + MemState post postDeps postLts <- get + put (MemState (uniqueDeleter post pre) postDeps postLts) -- replace any duplicates and union with the prior set + pure (Right ()) -- | Control that an `xobj` is OK to reference canBeReferenced :: TypeEnv -> Env -> XObj -> State MemState (Either TypeError ()) canBeReferenced typeEnv globalEnv xobj = - let Just t = xobjTy xobj + let t = fromMaybe (error "memory: xobj without type") $ xobjTy xobj isGlobalVariable = case xobj of XObj (Sym _ (LookupGlobal _ _)) _ _ -> True _ -> False @@ -590,9 +594,11 @@ refTargetIsAlive xobj = [] -> --trace ("Can't use reference " ++ pretty xobj ++ " (with lifetime '" ++ lt ++ "', depending on " ++ show deleterName ++ ") at " ++ prettyInfoFromXObj xobj ++ ", it's not alive here:\n" ++ show xobj ++ "\nMappings: " ++ prettyLifetimeMappings lifetimeMappings ++ "\nAlive: " ++ show deleters ++ "\n") $ --pure (Right xobj) - pure (case xobjObj xobj of - (Lst (LetPat _ _ body)) -> (Left (UsingDeadReference body deleterName)) - _ -> (Left (UsingDeadReference xobj deleterName))) + pure + ( case xobjObj xobj of + (Lst (LetPat _ _ body)) -> (Left (UsingDeadReference body deleterName)) + _ -> (Left (UsingDeadReference xobj deleterName)) + ) _ -> --trace ("CAN use reference " ++ pretty xobj ++ " (with lifetime '" ++ lt ++ "', depending on " ++ show deleterName ++ ") at " ++ prettyInfoFromXObj xobj ++ ", it's not alive here:\n" ++ show xobj ++ "\nMappings: " ++ prettyLifetimeMappings lifetimeMappings ++ "\nAlive: " ++ show deleters ++ "\n") $ pure (Right xobj) diff --git a/src/Meta.hs b/src/Meta.hs index 5eadfe40..f51fb84c 100644 --- a/src/Meta.hs +++ b/src/Meta.hs @@ -11,17 +11,17 @@ module Meta getString, getCompilerKey, validateAndSet, - CompilerKey(..), + CompilerKey (..), ) where +import Data.Either (fromRight) +import Data.Maybe (fromMaybe) import Info import qualified Map import Obj import SymPath import Types -import Data.Maybe(fromMaybe) -import Data.Either(fromRight) -------------------------------------------------------------------------------- -- builtin special meta key values @@ -31,7 +31,7 @@ data CompilerKey = CNAME -- Given a compiler key, returns the key name as a string along with a default value. toKeyValue :: CompilerKey -> (String, XObj) -toKeyValue CNAME = ("c-name", (XObj (Str "") Nothing Nothing)) +toKeyValue CNAME = ("c-name", (XObj (Str "") Nothing Nothing)) -- | Get the key associated with a compiler Meta key as a string. getCompilerKey :: CompilerKey -> String @@ -51,7 +51,7 @@ validateCompilerKeyValue CNAME _ = False validateAndSet :: MetaData -> CompilerKey -> XObj -> Either MetaData MetaData validateAndSet meta key val | validateCompilerKeyValue key (xobjObj val) = - Right (set (getCompilerKey key) val meta) + Right (set (getCompilerKey key) val meta) | otherwise = Left meta -------------------------------------------------------------------------------- @@ -332,12 +332,11 @@ machineReadableInfoFromXObj fppl xobj = Nothing -> "" -- | Obj with eXtra information. -data XObj - = XObj - { xobjObj :: Obj, - xobjInfo :: Maybe Info, - xobjTy :: Maybe Ty - } +data XObj = XObj + { xobjObj :: Obj, + xobjInfo :: Maybe Info, + xobjTy :: Maybe Ty + } deriving (Show, Eq, Ord) setObj :: XObj -> Obj -> XObj @@ -720,15 +719,14 @@ data EnvMode = ExternalEnv | InternalEnv | RecursionEnv deriving (Show, Eq, Gene instance Hashable EnvMode -- | Environment -data Env - = Env - { envBindings :: Map.Map String Binder, - envParent :: Maybe Env, - envModuleName :: Maybe String, - envUseModules :: Set.Set SymPath, - envMode :: EnvMode, - envFunctionNestingLevel :: Int -- Normal defn:s have 0, lambdas get +1 for each level of nesting - } +data Env = Env + { envBindings :: Map.Map String Binder, + envParent :: Maybe Env, + envModuleName :: Maybe String, + envUseModules :: Set.Set SymPath, + envMode :: EnvMode, + envFunctionNestingLevel :: Int -- Normal defn:s have 0, lambdas get +1 for each level of nesting + } deriving (Show, Eq, Generic) instance Hashable Env @@ -911,13 +909,12 @@ polymorphicSuffix signature actualType = type VisitedTypes = [Ty] -- | Templates are like macros, but defined inside the compiler and with access to the types they are instantiated with -data Template - = Template - { templateSignature :: Ty, - templateDeclaration :: Ty -> [Token], -- Will this parameterization ever be useful? - templateDefinition :: Ty -> [Token], - templateDependencies :: Ty -> [XObj] - } +data Template = Template + { templateSignature :: Ty, + templateDeclaration :: Ty -> [Token], -- Will this parameterization ever be useful? + templateDefinition :: Ty -> [Token], + templateDependencies :: Ty -> [XObj] + } instance Hashable Template where hashWithSalt s Template {..} = s `hashWithSalt` templateSignature @@ -937,7 +934,7 @@ data Token = TokTy Ty TokTyMode -- Some kind of type, will be looked up if it's a type variable. | TokC String -- Plain C code. | TokDecl -- Will emit the declaration (i.e. "foo(int x)"), this is useful - -- for avoiding repetition in the definition part of the template. + -- for avoiding repetition in the definition part of the template. | TokName -- Will emit the name of the instantiated function/variable. deriving (Eq, Ord) @@ -995,19 +992,25 @@ forceTy xobj = fromMaybe (error ("No type in " ++ show xobj)) (xobjTy xobj) data ExecutionMode = Repl | Build | BuildAndRun | Install String | Check deriving (Show, Eq) -- | Information needed by the REPL -data Context - = Context - { contextGlobalEnv :: Env, - contextInternalEnv :: Maybe Env, - contextTypeEnv :: TypeEnv, - contextPath :: [String], - contextProj :: Project, - contextLastInput :: String, - contextExecMode :: ExecutionMode, - contextHistory :: ![XObj] - } +data Context = Context + { contextGlobalEnv :: Env, + contextInternalEnv :: Maybe Env, + contextTypeEnv :: TypeEnv, + contextPath :: [String], + contextProj :: Project, + contextLastInput :: String, + contextExecMode :: ExecutionMode, + contextHistory :: ![XObj] + } deriving (Show, Generic) +-- required for Hashable >= 1.4.0.0 +instance Eq Context where + c == c' = + (contextGlobalEnv c) == (contextGlobalEnv c') + && (contextInternalEnv c) == (contextInternalEnv c') + && (contextTypeEnv c) == (contextTypeEnv c') + instance Hashable Context where hashWithSalt s Context {..} = s diff --git a/src/Parsing.hs b/src/Parsing.hs index eb4d8d0d..9a4388c5 100644 --- a/src/Parsing.hs +++ b/src/Parsing.hs @@ -292,22 +292,26 @@ escaped = do 'v' -> pure "\v" 'x' -> do hex <- Parsec.many1 (Parsec.oneOf "0123456789abcdefABCDEF") - let [(p, "")] = readHex hex - return [chr p] + case readHex hex of + [(p, "")] -> pure [chr p] + _ -> pure [] 'u' -> do hex <- Parsec.count 4 (Parsec.oneOf "0123456789abcdefABCDEF") - let [(p, "")] = readHex hex - return [chr p] + case readHex hex of + [(p, "")] -> pure [chr p] + _ -> pure [] 'U' -> do hex <- Parsec.count 8 (Parsec.oneOf "0123456789abcdefABCDEF") - let [(p, "")] = readHex hex - return [chr p] + case readHex hex of + [(p, "")] -> pure [chr p] + _ -> pure [] _ -> if elem c "01234567" then do hex <- Parsec.many1 (Parsec.oneOf "01234567") - let [(p, "")] = readHex (c : hex) - return [chr p] + case readHex (c : hex) of + [(p, "")] -> pure [chr p] + _ -> pure [] else pure ('\\' : [c]) escapedQuoteChar :: Parsec.Parsec String ParseState Char @@ -357,8 +361,9 @@ escapedHexChar = do _ <- Parsec.char 'u' hex <- Parsec.count 4 (Parsec.oneOf "0123456789abcdefABCDEF") incColumn 5 - let [(parsed, "")] = readHex hex - pure (toEnum parsed) + case readHex hex of + [(parsed, "")] -> pure (toEnum parsed) + _ -> pure '\0' aChar :: Parsec.Parsec String ParseState XObj aChar = do diff --git a/src/Polymorphism.hs b/src/Polymorphism.hs index d66856c3..4b1d4217 100644 --- a/src/Polymorphism.hs +++ b/src/Polymorphism.hs @@ -9,6 +9,7 @@ where import Data.Either (fromRight, rights) import Data.List (unionBy) +import Data.Maybe (fromMaybe) import Env import Managed import Obj @@ -32,7 +33,7 @@ nameOfPolymorphicFunction _ env functionType functionName = Right (_, (Binder _ (XObj (Lst (XObj (External (Just name)) _ _ : _)) _ _))) -> Just (SymPath [] name) Right (_, (Binder _ single)) -> - let Just t' = xobjTy single + let t' = fromMaybe (error "polymorphism: binder without type") $ xobjTy single (SymPath pathStrings name) = getPath single suffix = polymorphicSuffix t' functionType concretizedPath = SymPath pathStrings (name ++ suffix) @@ -124,7 +125,7 @@ findFunctionForMemberIncludePrimitives typeEnv env functionName functionType (me -- its generic ancestor. getConcretizedPath :: XObj -> Ty -> SymPath getConcretizedPath defn functionType = - let Just t' = xobjTy defn + let t' = fromMaybe (error "polymorphism: defn without type") $ xobjTy defn SymPath pathStrings name = getPath defn suffix = polymorphicSuffix t' functionType in SymPath pathStrings (name ++ suffix) diff --git a/src/Primitives.hs b/src/Primitives.hs index c10cf843..eac35fb6 100644 --- a/src/Primitives.hs +++ b/src/Primitives.hs @@ -135,7 +135,9 @@ primitiveImplements _ ctx x@(XObj (Sym interface@(SymPath _ _) _) _ _) (XObj (Sy warn = emitWarning (show (NonExistentInterfaceWarning x)) addToInterface :: Binder -> Binder -> IO (Context, Either EvalError XObj) addToInterface inter impl = - let (Right newCtx, maybeErr) = registerInInterface ctx impl inter + let (newCtx, maybeErr) = case registerInInterface ctx impl inter of + (Right nc, me) -> (nc, me) + _ -> error "primitives: failed to register in interface" in maybe (updateMeta impl newCtx) (handleError newCtx impl) maybeErr handleError :: Context -> Binder -> InterfaceError -> IO (Context, Either EvalError XObj) handleError context impl e@(AlreadyImplemented _ oldImplPath _ _) = @@ -210,7 +212,9 @@ define hidden ctx qualifiedXObj = pure ( Meta.getBinderMetaValue "implements" binder -- TODO: Direct qualification! - >>= \(XObj (Lst interfaces) _ _) -> pure (map Qualified interfaces) + >>= \x -> case x of + (XObj (Lst interfaces) _ _) -> pure (map Qualified interfaces) + _ -> pure [] ) >>= \maybeinterfaces -> pure (rights (fmap (lookupBinderInTypeEnv ctx . getQualifiedPath) (fromMaybe [] maybeinterfaces))) @@ -264,7 +268,7 @@ primitiveRegisterTypeWithFields ctx x t override members = let typeDefinition = XObj (Lst [XObj (ExternalType override) Nothing Nothing, XObj (Sym path Symbol) Nothing Nothing]) Nothing (Just TypeTy) path' = (qualifyPath ctx (SymPath [] typeModuleName)) update = \c -> insertInGlobalEnv' path' (toBinder typeModuleXObj) c >>= insertTypeBinder' path' (toBinder typeDefinition) - Right ctx' = update ctx + ctx' = fromRight (error "primitives: failed to update context in register type") $ update ctx -- TODO: Another case where define does not get formally qualified deps! contextWithDefs <- liftIO $ foldM (define True) ctx' (map Qualified deps) autoDerive @@ -325,7 +329,10 @@ primitiveInfo _ ctx target@(XObj (Sym path@(SymPath _ name) _) _ _) = implementsInterface binder binder' = maybe False - (\(XObj (Lst impls) _ _) -> getBinderPath binder `elem` map getPath impls) + ( \x -> case x of + (XObj (Lst impls) _ _) -> getBinderPath binder `elem` map getPath impls + _ -> False + ) (Meta.getBinderMetaValue "implements" binder') printIfFound :: Either ContextError Binder -> IO () printIfFound = either (const (pure ())) printer @@ -475,8 +482,8 @@ primitiveDefinterface xobj ctx nameXObj@(XObj (Sym path@(SymPath [] name) _) _ _ defInterface = let interface = defineInterface name t [] (xobjInfo nameXObj) binder = toBinder interface - Right ctx' = insertTypeBinder ctx (markQualified (SymPath [] name)) binder - Right newCtx = retroactivelyRegisterInInterface ctx' binder + ctx' = fromRight (error "primitives: couldn't insert type binder for interface") $ insertTypeBinder ctx (markQualified (SymPath [] name)) binder + newCtx = fromRight (error "primitives: couldn't retroactively register in interface") $ retroactivelyRegisterInInterface ctx' binder in (newCtx, dynamicNil) updateInterface binder = case binder of Binder _ (XObj (Lst (XObj (Interface foundType _) _ _ : _)) _ _) -> diff --git a/src/Project.hs b/src/Project.hs index e10017d2..726a1eee 100644 --- a/src/Project.hs +++ b/src/Project.hs @@ -24,41 +24,40 @@ instance Show Target where -- -- Otherwise, if the field is truly private and only for internal use in the -- compiler, add the field to the Project record but omit it from the keyMap. -data Project - = Project - { projectTitle :: String, - projectIncludes :: [Includer], - projectPreproc :: [String], - projectCFlags :: [String], - projectLibFlags :: [String], - projectPkgConfigFlags :: [String], - projectFiles :: [(FilePath, ReloadMode)], - projectAlreadyLoaded :: [FilePath], - projectEchoC :: Bool, - projectLibDir :: FilePath, - projectCarpDir :: FilePath, - projectOutDir :: FilePath, - projectDocsDir :: FilePath, - projectDocsLogo :: FilePath, - projectDocsPrelude :: String, - projectDocsURL :: String, - projectDocsGenerateIndex :: Bool, - projectDocsStyling :: String, - projectPrompt :: String, - projectCarpSearchPaths :: [FilePath], - projectPrintTypedAST :: Bool, - projectCompiler :: String, - projectTarget :: Target, - projectCore :: Bool, - projectEchoCompilationCommand :: Bool, - projectCanExecute :: Bool, - projectFilePathPrintLength :: FilePathPrintLength, - projectGenerateOnly :: Bool, - projectBalanceHints :: Bool, - projectForceReload :: Bool, -- Setting this to true will make the `load-once` command work just like `load`. - projectCModules :: [FilePath], - projectLoadStack :: [FilePath] - } +data Project = Project + { projectTitle :: String, + projectIncludes :: [Includer], + projectPreproc :: [String], + projectCFlags :: [String], + projectLibFlags :: [String], + projectPkgConfigFlags :: [String], + projectFiles :: [(FilePath, ReloadMode)], + projectAlreadyLoaded :: [FilePath], + projectEchoC :: Bool, + projectLibDir :: FilePath, + projectCarpDir :: FilePath, + projectOutDir :: FilePath, + projectDocsDir :: FilePath, + projectDocsLogo :: FilePath, + projectDocsPrelude :: String, + projectDocsURL :: String, + projectDocsGenerateIndex :: Bool, + projectDocsStyling :: String, + projectPrompt :: String, + projectCarpSearchPaths :: [FilePath], + projectPrintTypedAST :: Bool, + projectCompiler :: String, + projectTarget :: Target, + projectCore :: Bool, + projectEchoCompilationCommand :: Bool, + projectCanExecute :: Bool, + projectFilePathPrintLength :: FilePathPrintLength, + projectGenerateOnly :: Bool, + projectBalanceHints :: Bool, + projectForceReload :: Bool, -- Setting this to true will make the `load-once` command work just like `load`. + projectCModules :: [FilePath], + projectLoadStack :: [FilePath] + } projectFlags :: Project -> String projectFlags proj = joinWithSpace (projectCFlags proj ++ projectLibFlags proj) diff --git a/src/Qualify.hs b/src/Qualify.hs index d9a09ac4..3a65fe5e 100644 --- a/src/Qualify.hs +++ b/src/Qualify.hs @@ -23,11 +23,11 @@ import Data.Either (fromRight) import qualified Env as E import Info import qualified Map +import qualified Meta import Obj import qualified Set import SymPath import Util -import qualified Meta -------------------------------------------------------------------------------- -- Errors @@ -205,11 +205,14 @@ qualifyFunctionDefinition typeEnv globalEnv env x@(XObj (Lst [defn@(XObj (Defn _ envWithSelf <- fixLeft (E.insertX recursionEnv (SymPath [] functionName) sym) -- Copy the use modules from the local env to ensure they are available from the function env. functionEnv <- fixLeft (pure ((E.nested (Just envWithSelf) (Just (functionName ++ "-function-env")) 0) {envUseModules = (envUseModules env)})) - envWithArgs <- fixLeft (foldM (\e arg@(XObj (Sym path _) _ _) -> E.insertX e path arg) functionEnv argsArr) + envWithArgs <- fixLeft (foldM go functionEnv argsArr) qualifiedBody <- liftM unQualified (setFullyQualifiedSymbols typeEnv globalEnv envWithArgs body) pure (Qualified (XObj (Lst [defn, sym, args, qualifiedBody]) i t)) where fixLeft = replaceLeft (FailedToQualifyDeclarationName x) + go :: Env -> XObj -> Either E.EnvironmentError Env + go e arg@(XObj (Sym path _) _ _) = E.insertX e path arg + go e _ = pure e qualifyFunctionDefinition _ _ _ xobj = Left $ FailedToQualifyDeclarationName xobj -- | Qualify the symbols in a lambda body. @@ -217,10 +220,14 @@ qualifyLambda :: Qualifier qualifyLambda typeEnv globalEnv env x@(XObj (Lst [fn@(XObj (Fn _ _) _ _), args@(XObj (Arr argsArr) _ _), body]) i t) = let lvl = envFunctionNestingLevel env functionEnv = Env Map.empty (Just env) Nothing Set.empty InternalEnv (lvl + 1) - in (replaceLeft (FailedToQualifySymbols x) (foldM (\e arg@(XObj (Sym path _) _ _) -> E.insertX e path arg) functionEnv argsArr)) + in (replaceLeft (FailedToQualifySymbols x) (foldM go functionEnv argsArr)) >>= \envWithArgs -> liftM unQualified (setFullyQualifiedSymbols typeEnv globalEnv envWithArgs body) >>= \qualifiedBody -> pure (Qualified (XObj (Lst [fn, args, qualifiedBody]) i t)) + where + go :: Env -> XObj -> Either E.EnvironmentError Env + go e arg@(XObj (Sym path _) _ _) = E.insertX e path arg + go e _ = pure e qualifyLambda _ _ _ xobj = Left $ FailedToQualifySymbols xobj -- | Qualify the symbols in a The form's body. @@ -246,7 +253,7 @@ qualifyLet typeEnv globalEnv env x@(XObj (Lst [letExpr@(XObj Let _ _), bind@(XOb | not (all isSym (evenIndices bindings)) = Right $ Qualified $ XObj (Lst [letExpr, bind, body]) i t -- Leave it untouched for the compiler to find the error. | otherwise = do - let Just ii = i + let ii = infoOrUnknown i lvl = envFunctionNestingLevel env innerEnv = Env Map.empty (Just env) (Just ("let-env-" ++ show (infoIdentifier ii))) Set.empty InternalEnv lvl (innerEnv', qualifiedBindings) <- foldM qualifyBinding (innerEnv, []) (pairwise bindings) @@ -264,7 +271,7 @@ qualifyLet typeEnv globalEnv env x@(XObj (Lst [letExpr@(XObj Let _ _), bind@(XOb -- However, we also need to ensure captured variables are still marked -- as such, which is based on env nesting level, and we need to ensure -- the recursive reference isn't accidentally captured. - let Just origin = E.parent e + let origin = E.parentOrEmpty e recursionEnv <- fixLeft (pure (E.recursive (Just e) (Just ("let-recurse-env")) 0)) envWithSelf <- fixLeft (E.insertX recursionEnv path s) qualified <- liftM unQualified (setFullyQualifiedSymbols typeEnv globalEnv (E.setParent e (E.setParent origin envWithSelf)) o) @@ -291,7 +298,7 @@ qualifyMatch typeEnv globalEnv env (XObj (Lst (matchExpr@(XObj (Match _) _ _) : qualifiedCases <- pure . map (map unQualified) =<< mapM qualifyCases (pairwise casesXObjs) pure (Qualified (XObj (Lst (matchExpr : qualifiedExpr : concat qualifiedCases)) i t)) where - Just ii = i + ii = infoOrUnknown i lvl = envFunctionNestingLevel env -- Create an inner environment for each case. innerEnv :: Env @@ -378,18 +385,19 @@ qualifySym typeEnv globalEnv localEnv xobj@(XObj (Sym path@(SymPath _ name) _) i nakedInit modenv resolve origin found (Binder meta xobj') = let cname = (Meta.getString (Meta.getCompilerKey Meta.CNAME) meta) - modality = if (null cname) - then (LookupGlobal (if isExternalFunction xobj' then ExternalCode else CarpLand) (definitionMode xobj')) - else (LookupGlobalOverride cname) + modality = + if (null cname) + then (LookupGlobal (if isExternalFunction xobj' then ExternalCode else CarpLand) (definitionMode xobj')) + else (LookupGlobalOverride cname) in if (isTypeDef xobj') - then - ( (replaceLeft (FailedToFindSymbol xobj') (fmap (globalEnv,) (E.searchValue globalEnv path))) - >>= \(origin', (e', binder)) -> resolve (E.prj origin') (E.prj e') binder - ) - else case envMode (E.prj found) of - RecursionEnv -> pure (XObj (Sym (getPath xobj') LookupRecursive) i t) - InternalEnv -> pure (XObj (Sym (getPath xobj') (LookupLocal (captureOrNot found origin))) i t) - ExternalEnv -> pure (XObj (Sym (getPath xobj') modality) i t) + then + ( (replaceLeft (FailedToFindSymbol xobj') (fmap (globalEnv,) (E.searchValue globalEnv path))) + >>= \(origin', (e', binder)) -> resolve (E.prj origin') (E.prj e') binder + ) + else case envMode (E.prj found) of + RecursionEnv -> pure (XObj (Sym (getPath xobj') LookupRecursive) i t) + InternalEnv -> pure (XObj (Sym (getPath xobj') (LookupLocal (captureOrNot found origin))) i t) + ExternalEnv -> pure (XObj (Sym (getPath xobj') modality) i t) resolveMulti :: (Show e, E.Environment e) => SymPath -> [(e, Binder)] -> Either QualificationError XObj resolveMulti _ [] = Left (FailedToFindSymbol xobj) diff --git a/src/RenderDocs.hs b/src/RenderDocs.hs index 56cee97c..092002e5 100644 --- a/src/RenderDocs.hs +++ b/src/RenderDocs.hs @@ -7,6 +7,7 @@ import Control.Monad (when) import qualified Data.List as List import Data.Maybe (fromMaybe) import Data.Text as Text +import qualified Env as E import qualified Map import qualified Meta import Obj @@ -27,10 +28,14 @@ beautifyType t = mappings = Map.fromList ( List.zip - (List.map (\(VarTy name) -> name) tys) + (List.map go tys) (List.map (VarTy . (: [])) ['a' ..]) ) in replaceTyVars mappings t + where + go :: Ty -> String + go (VarTy name) = name + go _ = "" -- called on a non var type. saveDocsForEnvs :: Project -> [(SymPath, Binder)] -> IO () saveDocsForEnvs ctx pathsAndEnvBinders = @@ -63,7 +68,11 @@ saveDocsForEnvs ctx pathsAndEnvBinders = ) ) in envs - ++ getDependenciesForEnvs (Prelude.map (\(n, Binder _ (XObj (Mod env _) _ _)) -> (n, env)) envs) + ++ getDependenciesForEnvs (Prelude.map go envs) + where + go :: (SymPath, Binder) -> (SymPath, Env) + go (n, Binder _ (XObj (Mod env _) _ _)) = (n, env) + go _ = ((SymPath [] ""), E.empty) -- | This function expects a binder that contains an environment, anything else is a runtime error. getEnvAndMetaFromBinder :: Binder -> (Env, MetaData) diff --git a/src/StartingEnv.hs b/src/StartingEnv.hs index 7770cac3..066dcd6f 100644 --- a/src/StartingEnv.hs +++ b/src/StartingEnv.hs @@ -3,6 +3,7 @@ module StartingEnv where import qualified ArrayTemplates import qualified BoxTemplates import Commands +import Data.Maybe (fromMaybe) import qualified Env as E import Eval import Info @@ -148,7 +149,7 @@ functionModule = } where bindEnv env = - let Just name = envModuleName env + let name = fromMaybe (error "env has no module name") $ envModuleName env meta = Meta.set "hidden" trueXObj emptyMeta in (name, Binder meta (XObj (Mod env E.empty) Nothing Nothing)) bindings = Map.fromList (map (bindEnv . generateInnerFunctionModule) [0 .. maxArity]) @@ -380,7 +381,7 @@ dynamicStringModule = where path = ["Dynamic", "String"] bindings = - Map.fromList $unaries ++ binaries ++ ternaries + Map.fromList $ unaries ++ binaries ++ ternaries spath = SymPath path unaries = let f = addUnaryCommand . spath @@ -429,7 +430,7 @@ dynamicSymModule = } where path = ["Dynamic", "Symbol"] - bindings = Map.fromList $unaries ++ binaries + bindings = Map.fromList $ unaries ++ binaries spath = SymPath path unaries = let f = addUnaryCommand . spath @@ -455,7 +456,7 @@ dynamicProjectModule = } where path = ["Dynamic", "Project"] - bindings = Map.fromList $unaries ++ binaries + bindings = Map.fromList $ unaries ++ binaries spath = SymPath path unaries = let f = addUnaryCommand . spath diff --git a/src/StaticArrayTemplates.hs b/src/StaticArrayTemplates.hs index fff8f86d..e9edaa2b 100644 --- a/src/StaticArrayTemplates.hs +++ b/src/StaticArrayTemplates.hs @@ -1,3 +1,5 @@ +{-# LANGUAGE LambdaCase #-} + module StaticArrayTemplates where import qualified ArrayTemplates @@ -31,8 +33,9 @@ templateUnsafeNth = "}" ] ) - ( \(FuncTy [RefTy _ _, _] _ _) -> - [] + ( \case + (FuncTy [RefTy _ _, _] _ _) -> [] + _ -> error "static array templates: nth called on non array" ) templateLength :: (String, Binder) @@ -47,8 +50,10 @@ templateLength = defineTypeParameterizedTemplate templateCreator path t docs t (const (toTemplate "int $NAME (Array *a)")) (const (toTemplate "$DECL { return (*a).len; }")) - ( \(FuncTy [RefTy arrayType _] _ _) -> - depsForDeleteFunc typeEnv env arrayType + ( \case + (FuncTy [RefTy arrayType _] _ _) -> + depsForDeleteFunc typeEnv env arrayType + _ -> error "static array templates: length called on non array" ) templateDeleteArray :: (String, Binder) @@ -62,13 +67,17 @@ templateDeleteArray = defineTypeParameterizedTemplate templateCreator path t doc Template t (const (toTemplate "void $NAME (Array a)")) - ( \(FuncTy [arrayType] UnitTy _) -> - [TokDecl, TokC "{\n"] - ++ deleteTy typeEnv env arrayType - ++ [TokC "}\n"] + ( \case + (FuncTy [arrayType] UnitTy _) -> + [TokDecl, TokC "{\n"] + ++ deleteTy typeEnv env arrayType + ++ [TokC "}\n"] + _ -> error "static array templates: delete called on non array" ) - ( \(FuncTy [StructTy _ [insideType]] UnitTy _) -> - depsForDeleteFunc typeEnv env insideType + ( \case + (FuncTy [StructTy _ [insideType]] UnitTy _) -> + depsForDeleteFunc typeEnv env insideType + _ -> error "static array templates: delete called on non array" ) deleteTy :: TypeEnv -> Env -> Ty -> [Token] @@ -90,22 +99,26 @@ templateAsetBang = defineTypeParameterizedTemplate templateCreator path t docs Template t (const (toTemplate "void $NAME (Array *aRef, int n, $t newValue)")) - ( \(FuncTy [_, _, insideTy] _ _) -> - let deleter = ArrayTemplates.insideArrayDeletion typeEnv env insideTy - in ( toTemplate $ - unlines - [ "$DECL {", - " Array a = *aRef;", - " assert(n >= 0);", - " assert(n < a.len);", - deleter "n", - " (($t*)a.data)[n] = newValue;", - "}" - ] - ) + ( \case + (FuncTy [_, _, insideTy] _ _) -> + let deleter = ArrayTemplates.insideArrayDeletion typeEnv env insideTy + in ( toTemplate $ + unlines + [ "$DECL {", + " Array a = *aRef;", + " assert(n >= 0);", + " assert(n < a.len);", + deleter "n", + " (($t*)a.data)[n] = newValue;", + "}" + ] + ) + _ -> error "static array templates: aset bang called on non array" ) - ( \(FuncTy [RefTy arrayType _, _, _] _ _) -> - depsForDeleteFunc typeEnv env arrayType + ( \case + (FuncTy [RefTy arrayType _, _, _] _ _) -> + depsForDeleteFunc typeEnv env arrayType + _ -> error "static array templates: aset bang called on non array" ) templateAsetUninitializedBang :: (String, Binder) @@ -118,23 +131,27 @@ templateAsetUninitializedBang = defineTypeParameterizedTemplate templateCreator \_ _ -> Template t - ( \(FuncTy [_, _, valueType] _ _) -> - case valueType of - UnitTy -> toTemplate "void $NAME (Array *aRef, int n)" - _ -> toTemplate "void $NAME (Array *aRef, int n, $t newValue)" + ( \case + (FuncTy [_, _, valueType] _ _) -> + case valueType of + UnitTy -> toTemplate "void $NAME (Array *aRef, int n)" + _ -> toTemplate "void $NAME (Array *aRef, int n, $t newValue)" + _ -> error "static array templates: aset called on non array" ) - ( \(FuncTy [_, _, valueType] _ _) -> - case valueType of - UnitTy -> ArrayTemplates.unitSetterTemplate - _ -> - multilineTemplate - [ "$DECL {", - " Array a = *aRef;", - " assert(n >= 0);", - " assert(n < a.len);", - " (($t*)a.data)[n] = newValue;", - "}" - ] + ( \case + (FuncTy [_, _, valueType] _ _) -> + case valueType of + UnitTy -> ArrayTemplates.unitSetterTemplate + _ -> + multilineTemplate + [ "$DECL {", + " Array a = *aRef;", + " assert(n >= 0);", + " assert(n < a.len);", + " (($t*)a.data)[n] = newValue;", + "}" + ] + _ -> error "static array templates: aset called on non array" ) (const []) @@ -146,13 +163,17 @@ templateStrArray = defineTypeParameterizedTemplate templateCreator path t docs Template t (const (toTemplate "String $NAME (Array* a)")) - ( \(FuncTy [RefTy arrayType _] StringTy _) -> - [TokDecl, TokC " {\n"] - ++ ArrayTemplates.strTy typeEnv env arrayType - ++ [TokC "}\n"] + ( \case + (FuncTy [RefTy arrayType _] StringTy _) -> + [TokDecl, TokC " {\n"] + ++ ArrayTemplates.strTy typeEnv env arrayType + ++ [TokC "}\n"] + _ -> error "static array templates: str called on non array" ) - ( \(FuncTy [RefTy (StructTy _ [insideType]) _] StringTy _) -> - depsForPrnFunc typeEnv env insideType + ( \case + (FuncTy [RefTy (StructTy _ [insideType]) _] StringTy _) -> + depsForPrnFunc typeEnv env insideType + _ -> error "static array templates: str called on non array" ) path = SymPath ["StaticArray"] "str" t = FuncTy [RefTy (StructTy concreteArray [VarTy "a"]) (VarTy "q")] StringTy StaticLifetimeTy diff --git a/src/Sumtypes.hs b/src/Sumtypes.hs index 634ca4b9..a9760432 100644 --- a/src/Sumtypes.hs +++ b/src/Sumtypes.hs @@ -137,9 +137,13 @@ initers candidate = mapM binderForCaseInit (TC.getFields candidate) ft = FuncTy tys generic StaticLifetimeTy binderPath = SymPath (TC.getFullPath candidate) fieldname t = (FuncTy tys (VarTy "p") StaticLifetimeTy) - decl = \(FuncTy _ concrete _) -> tokensForCaseInitDecl generic concrete field - body = \(FuncTy _ concrete _) -> tokensForCaseInit alloc generic concrete field - deps tenv env = \(FuncTy _ concrete _) -> either (const []) id (concretizeType tenv env concrete) + decl (FuncTy _ concrete _) = tokensForCaseInitDecl generic concrete field + decl _ = error "sumtypes: genericCaseInit called with non function type" + body (FuncTy _ concrete _) = tokensForCaseInit alloc generic concrete field + body _ = error "sumtypes: genericCaseInit called with non function type" + deps tenv env = \typ -> case typ of + (FuncTy _ concrete _) -> either (const []) id (concretizeType tenv env concrete) + _ -> [] temp = TemplateCreator $ \tenv env -> Template t decl body (deps tenv env) in defineTypeParameterizedTemplate temp binderPath ft docs genericCaseInit _ _ = error "genericCaseInit" @@ -148,8 +152,10 @@ initers candidate = mapM binderForCaseInit (TC.getFields candidate) binderForTag :: BinderGen binderForTag candidate = let t = FuncTy [RefTy (TC.toType candidate) (VarTy "q")] IntTy StaticLifetimeTy - decl = \(FuncTy [RefTy struct _] _ _) -> toTemplate $ proto struct - body = \(FuncTy [RefTy struct _] _ _) -> toTemplate $ proto struct ++ " { return p->_tag; }" + decl (FuncTy [RefTy struct _] _ _) = toTemplate $ proto struct + decl _ = error "sumtypes: binderForTag called with non function type" + body (FuncTy [RefTy struct _] _ _) = toTemplate $ proto struct ++ " { return p->_tag; }" + body _ = error "sumtypes: binderForTag called with non function type" deps = const [] path' = SymPath (TC.getFullPath candidate) "get-tag" temp = Template t decl body deps diff --git a/src/Template.hs b/src/Template.hs index 3bc0a4f6..5fb8e604 100644 --- a/src/Template.hs +++ b/src/Template.hs @@ -69,9 +69,8 @@ concretizeTypesInToken mappings cName decl token = -- | The code needed to correctly call a lambda from C. templateCodeForCallingLambda :: String -> Ty -> [String] -> String -templateCodeForCallingLambda functionName t args = - let FuncTy argTys retTy lt = t - castToFnWithEnv = tyToCast (FuncTy (lambdaEnvTy : argTys) retTy lt) +templateCodeForCallingLambda functionName t@(FuncTy argTys retTy lt) args = + let castToFnWithEnv = tyToCast (FuncTy (lambdaEnvTy : argTys) retTy lt) castToFn = tyToCast t in functionName ++ ".env ? " ++ "((" @@ -92,12 +91,13 @@ templateCodeForCallingLambda functionName t args = ++ ".callback)(" ++ joinWithComma args ++ ")" +templateCodeForCallingLambda _ _ _ = "" -- called w/ non function type, emit nothing. -- | Must cast a lambda:s .callback member to the correct type to be able to call it. tyToCast :: Ty -> String -tyToCast t = - let FuncTy argTys retTy _ = t - in "§(Fn [" ++ joinWithSpace (map show argTys) ++ "] " ++ show retTy ++ ")" -- Note! The '§' means that the emitted type will be "raw" and not converted to 'Lambda'. +tyToCast (FuncTy argTys retTy _) = + "§(Fn [" ++ joinWithSpace (map show argTys) ++ "] " ++ show retTy ++ ")" -- Note! The '§' means that the emitted type will be "raw" and not converted to 'Lambda'. +tyToCast _ = "" -- called w/ non function type. Emit nothing. ---------------------------------------------------------------------------------------------------------- -- ACTUAL TEMPLATES diff --git a/src/TypeError.hs b/src/TypeError.hs index f3470a06..da954bae 100644 --- a/src/TypeError.hs +++ b/src/TypeError.hs @@ -525,10 +525,12 @@ beautifyTy mappings = f bmappings = beautification mappings beautification :: TypeMappings -> Map.Map String String beautification m = - Map.fromList $ zip (map (\(VarTy name) -> name) tys) beautList + Map.fromList $ zip (map go tys) beautList where tys = nub $ concat $ typeVariablesInOrderOfAppearance <$> tys' tys' = snd <$> Map.assocs m + go (VarTy name) = name + go _ = "" -- called on a non var type. Emit nothing. beautList = [c : s | s <- "" : beautList, c <- ['a' .. 'z']] typeVariablesInOrderOfAppearance :: Ty -> [Ty] |