From 14b608a36e7fb6491924ed0e0f710a266edbc6a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Sved=C3=A4ng?= Date: Tue, 28 Apr 2020 10:06:17 +0200 Subject: [PATCH] Static array kinda works now. --- core/Core.carp | 1 + core/StaticArray.carp | 30 ++++ docs/core/StaticArray.html | 338 +++++++++++++++++++++++++++++++++++++ examples/static_array.carp | 6 +- src/ArrayTemplates.hs | 2 +- src/StartingEnv.hs | 5 +- src/StaticArray.hs | 61 +++++++ 7 files changed, 439 insertions(+), 4 deletions(-) create mode 100644 core/StaticArray.carp create mode 100644 docs/core/StaticArray.html diff --git a/core/Core.carp b/core/Core.carp index b38dcd9d..ff2f0957 100644 --- a/core/Core.carp +++ b/core/Core.carp @@ -35,6 +35,7 @@ (load "Double.carp") (load "Float.carp") (load "Tuples.carp") +(load "StaticArray.carp") (load "Array.carp") (load "Char.carp") (load "String.carp") diff --git a/core/StaticArray.carp b/core/StaticArray.carp new file mode 100644 index 00000000..11cffce5 --- /dev/null +++ b/core/StaticArray.carp @@ -0,0 +1,30 @@ +(defmodule StaticArray + + (defndynamic foreach-internal [var xs expr] + (let [xsym (gensym-with 'xs) + len (gensym-with 'len) + i (gensym-with 'i)] + (list 'let [xsym xs + len (list 'StaticArray.length xsym)] + (list 'for [i 0 len] + (list 'let [var (list 'StaticArray.unsafe-nth xsym i)] + expr))))) + + ;; NOTE: Exact copy of the Array.foreach macro, could be made "generic" by removing the module prefixes. + (defmacro foreach [binding expr] + (StaticArray.foreach-internal (car binding) (cadr binding) expr)) + + (doc map! "Maps a function over the static array `xs`, mutating it in place. The difference to Array.endo-map (which does the same thing internally) is that this function takes a ref (since you can never have static arrays as values) and that it returns ().") + (defn map! [xs f] + (for [i 0 (StaticArray.length xs)] + (StaticArray.aset! xs i (~f (StaticArray.unsafe-nth xs i))))) + + ;; NOTE: Exact copy of the Array.reduce function. + (defn reduce [f x xs] + (let [total x] + (do + (for [i 0 (StaticArray.length xs)] + (set! total (~f total (StaticArray.unsafe-nth xs i)))) + total))) + + ) diff --git a/docs/core/StaticArray.html b/docs/core/StaticArray.html new file mode 100644 index 00000000..f5e53524 --- /dev/null +++ b/docs/core/StaticArray.html @@ -0,0 +1,338 @@ + + + + + + + + + +
+ +

+ StaticArray +

+
+ +
+
+ +

+ aset! +

+
+
+ template +
+

+ (λ [(Ref (StaticArray a) b), Int, a] ()) +

+ + + +

+

sets an array element at the index n to a new value in place.

+ +

+
+
+ +

+ delete +

+
+
+ template +
+

+ (λ [(StaticArray a)] ()) +

+ + + +

+

deletes a static array. This function should not be called manually (there shouldn't be a way to create value types of type StaticArray).

+ +

+
+
+ +

+ foreach +

+
+
+ macro +
+

+ Macro +

+
+                    (foreach binding expr)
+                
+

+ +

+
+
+ +

+ foreach-internal +

+
+
+ dynamic +
+

+ Dynamic +

+
+                    (foreach-internal var xs expr)
+                
+

+ +

+
+
+ +

+ length +

+
+
+ template +
+

+ (λ [(Ref (StaticArray a) b)] Int) +

+ + + +

+

gets the length of the static array.

+ +

+
+
+ +

+ map! +

+
+
+ defn +
+

+ (λ [(Ref (StaticArray a) b), (Ref (λ [(Ref a b)] a c) d)] ()) +

+
+                    (map! xs f)
+                
+

+

Maps a function over the static array xs, mutating it in place. The difference to Array.endo-map (which does the same thing internally) is that this function takes a ref (since you can never have static arrays as values) and that it returns ().

+ +

+
+
+ +

+ reduce +

+
+
+ defn +
+

+ (λ [(Ref (λ [a, (Ref b c)] a d) e), a, (Ref (StaticArray b) c)] a) +

+
+                    (reduce f x xs)
+                
+

+ +

+
+
+ +

+ str +

+
+
+ template +
+

+ (λ [(Ref (StaticArray a) b)] String) +

+ + + +

+

converts a static array to a string.

+ +

+
+
+ +

+ unsafe-nth +

+
+
+ template +
+

+ (λ [(Ref (StaticArray a) b), Int] (Ref a b)) +

+ + + +

+

gets a reference to the nth element from a static array a.

+ +

+
+
+ + diff --git a/examples/static_array.carp b/examples/static_array.carp index 6e66470a..b4a33e81 100644 --- a/examples/static_array.carp +++ b/examples/static_array.carp @@ -1,4 +1,6 @@ (defn main [] (Debug.memory-logged - (let [xs $[@"a" @"b" @"c"]] - (println* (StaticArray.unsafe-nth xs 2))))) + (let [xs $[1 2 3 4 5]] + (do + (StaticArray.map! xs &(fn [x] (+ @x 1))) + (println* (StaticArray.reduce &(fn [total x] (+ total @x)) 0 xs)))))) diff --git a/src/ArrayTemplates.hs b/src/ArrayTemplates.hs index bcada185..2366638e 100644 --- a/src/ArrayTemplates.hs +++ b/src/ArrayTemplates.hs @@ -431,7 +431,7 @@ templateStrArray = defineTypeParameterizedTemplate templateCreator path t docs -- | TODO: move this into the templateStrArray function? strTy :: TypeEnv -> Env -> Ty -> [Token] -strTy typeEnv env (StructTy "Array" [innerType]) = +strTy typeEnv env (StructTy _ [innerType]) = [ TokC "" , TokC " String temp = NULL;\n" , TokC $ calculateStrSize typeEnv env innerType diff --git a/src/StartingEnv.hs b/src/StartingEnv.hs index d0d2042b..93ce0080 100644 --- a/src/StartingEnv.hs +++ b/src/StartingEnv.hs @@ -14,6 +14,7 @@ import Commands import Parsing import Eval import Concretize +import Debug.Trace (trace) -- | These modules will be loaded in order before any other code is evaluated. coreModules :: String -> [String] @@ -57,6 +58,8 @@ staticArrayModule = Env { envBindings = bindings where bindings = Map.fromList [ StaticArray.templateUnsafeNth , StaticArray.templateLength , StaticArray.templateDeleteArray + , StaticArray.templateAsetBang + , StaticArray.templateStrArray ] -- | The Pointer module contains functions for dealing with pointers. @@ -461,7 +464,7 @@ startingTypeEnv = Env { envBindings = bindings builtInSymbolInfo , interfaceBinder "str" (FuncTy [VarTy "a"] StringTy StaticLifetimeTy) - (SymPath ["Array"] "str" : registerFunctionFunctionsWithInterface "str") + ((SymPath ["Array"] "str") : (SymPath ["StaticArray"] "str") : registerFunctionFunctionsWithInterface "str") builtInSymbolInfo , interfaceBinder "prn" (FuncTy [VarTy "a"] StringTy StaticLifetimeTy) diff --git a/src/StaticArray.hs b/src/StaticArray.hs index c27a21ec..df9c2256 100644 --- a/src/StaticArray.hs +++ b/src/StaticArray.hs @@ -66,3 +66,64 @@ deleteTy typeEnv env (StructTy _ [innerType]) = , TokC " }\n" ] deleteTy _ _ _ = [] + +-- templateEMap :: (String, Binder) +-- templateEMap = +-- let fTy = FuncTy [VarTy "a"] (VarTy "a") (VarTy "fq") +-- aTy = RefTy (StructTy "StaticArray" [VarTy "a"]) (VarTy "q") +-- bTy = RefTy (StructTy "StaticArray" [VarTy "a"]) (VarTy "q") +-- elem = "((($a*)a.data)[i])" +-- in defineTemplate +-- (SymPath ["StaticArray"] "endo-map") +-- (FuncTy [RefTy fTy (VarTy "q"), aTy] bTy StaticLifetimeTy) +-- "applies a function `f` to an array `a`. The type of the elements cannot change." +-- (toTemplate "Array $NAME(Lambda *f, Array a)") -- Lambda used to be $(Fn [a] a) +-- (toTemplate $ unlines +-- ["$DECL { " +-- ," for(int i = 0; i < a.len; ++i) {" +-- ," (($a*)a.data)[i] = " ++ templateCodeForCallingLambda "(*f)" fTy [elem] ++ ";" +-- ," }" +-- ," return a;" +-- ,"}" +-- ]) +-- (\(FuncTy [RefTy t@(FuncTy fArgTys fRetTy _) _, arrayType] _ _) -> +-- [defineFunctionTypeAlias t, defineFunctionTypeAlias (FuncTy (lambdaEnvTy : fArgTys) fRetTy StaticLifetimeTy)]) + +templateAsetBang :: (String, Binder) +templateAsetBang = defineTypeParameterizedTemplate templateCreator path t docs + where path = SymPath ["StaticArray"] "aset!" + t = FuncTy [RefTy (StructTy "StaticArray" [VarTy "t"]) (VarTy "q"), IntTy, VarTy "t"] UnitTy StaticLifetimeTy + docs = "sets an array element at the index `n` to a new value in place." + templateCreator = TemplateCreator $ + \typeEnv env -> + 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;" + ,"}"])) + (\(FuncTy [RefTy arrayType _, _, _] _ _) -> + depsForDeleteFunc typeEnv env arrayType) + +templateStrArray :: (String, Binder) +templateStrArray = defineTypeParameterizedTemplate templateCreator path t docs + where templateCreator = TemplateCreator $ + \typeEnv env -> + Template + t + (const (toTemplate "String $NAME (Array* a)")) + (\(FuncTy [RefTy arrayType _] StringTy _) -> + [TokDecl, TokC " {\n"] ++ + ArrayTemplates.strTy typeEnv env arrayType ++ + [TokC "}\n"]) + (\(FuncTy [RefTy arrayType@(StructTy "StaticArray" [insideType]) _] StringTy _) -> + depsForPrnFunc typeEnv env insideType) + path = SymPath ["StaticArray"] "str" + t = FuncTy [RefTy (StructTy "StaticArray" [VarTy "a"]) (VarTy "q")] StringTy StaticLifetimeTy + docs = "converts a static array to a string."