From 205bba0e931126a233c5e91ea023db52a500d7a1 Mon Sep 17 00:00:00 2001 From: Elias Castegren Date: Thu, 20 Apr 2017 19:35:52 +0200 Subject: [PATCH 01/18] Allow any type to instantiate an unsafe parameter (#785) This commit allows using any type where an `unsafe` parameter is expected, making `unsafe` the escape hatch for parametric constructs. It is needed for the implementation of `bestow`. --- src/tests/encore/parametric/linear.enc | 18 ++++++++++++++++++ .../parametric/{unsafe.fail => linear.fail} | 0 src/tests/encore/parametric/unsafe.enc | 13 +++++++------ src/tests/encore/parametric/unsafe.out | 1 + src/types/Types.hs | 2 +- 5 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 src/tests/encore/parametric/linear.enc rename src/tests/encore/parametric/{unsafe.fail => linear.fail} (100%) create mode 100644 src/tests/encore/parametric/unsafe.out diff --git a/src/tests/encore/parametric/linear.enc b/src/tests/encore/parametric/linear.enc new file mode 100644 index 000000000..eed01a194 --- /dev/null +++ b/src/tests/encore/parametric/linear.enc @@ -0,0 +1,18 @@ +read class Duplicator[t] + def duplicate(x : t) : (t, t) + (x, x) + end +end + +linear class Token +end + +active class Main + def main(args : [String]) : unit + val duplicator = new Duplicator[Token] + var x = new Token + match duplicator.duplicate(x) with + case (y, y') => println("all your linear are belong to us") + end + end +end \ No newline at end of file diff --git a/src/tests/encore/parametric/unsafe.fail b/src/tests/encore/parametric/linear.fail similarity index 100% rename from src/tests/encore/parametric/unsafe.fail rename to src/tests/encore/parametric/linear.fail diff --git a/src/tests/encore/parametric/unsafe.enc b/src/tests/encore/parametric/unsafe.enc index eed01a194..d882c67e9 100644 --- a/src/tests/encore/parametric/unsafe.enc +++ b/src/tests/encore/parametric/unsafe.enc @@ -1,6 +1,7 @@ -read class Duplicator[t] - def duplicate(x : t) : (t, t) - (x, x) +unsafe class Duplicator[unsafe t] + var f : t + def duplicate() : (t, t) + (this.f, this.f) end end @@ -10,9 +11,9 @@ end active class Main def main(args : [String]) : unit val duplicator = new Duplicator[Token] - var x = new Token - match duplicator.duplicate(x) with - case (y, y') => println("all your linear are belong to us") + duplicator.f = new Token + match duplicator.duplicate() with + case (y, y') => println("All your linear are belong to us") end end end \ No newline at end of file diff --git a/src/tests/encore/parametric/unsafe.out b/src/tests/encore/parametric/unsafe.out new file mode 100644 index 000000000..e69910a6a --- /dev/null +++ b/src/tests/encore/parametric/unsafe.out @@ -0,0 +1 @@ +All your linear are belong to us diff --git a/src/types/Types.hs b/src/types/Types.hs index 7de9a797a..c2e0dbac5 100644 --- a/src/types/Types.hs +++ b/src/types/Types.hs @@ -187,7 +187,7 @@ modeSubtypeOf ty1 ty2 = where hasMatchingMode modes mode | modeIsSharable mode = mode `elem` modes || Sharable `elem` modes - | otherwise = mode `elem` modes + | otherwise = mode `elem` modes || Unsafe `elem` modes modeIsSharable Read = True modeIsSharable Active = True From 0348f74ed91edd54725fdc276cca7b766f1e75c4 Mon Sep 17 00:00:00 2001 From: supercooldave Date: Sun, 23 Apr 2017 16:38:00 +0200 Subject: [PATCH 02/18] Added regression test for issue #18 (#787) --- src/tests/encore/regressions/18.enc | 28 ++++++++++++++++++++++++++++ src/tests/encore/regressions/18.out | 1 + 2 files changed, 29 insertions(+) create mode 100644 src/tests/encore/regressions/18.enc create mode 100644 src/tests/encore/regressions/18.out diff --git a/src/tests/encore/regressions/18.enc b/src/tests/encore/regressions/18.enc new file mode 100644 index 000000000..d0132e9ce --- /dev/null +++ b/src/tests/encore/regressions/18.enc @@ -0,0 +1,28 @@ +local class Filter + def cancel(i : int) : unit + println(i) + end + + def forall(f : int -> unit) : unit + f(10) + end +end + +active class Pif + val filter : Filter + + def init() : unit + this.filter = new Filter + end + + def foo() : unit + val action = fun (i : int) : unit => this.filter.cancel(i) + this.filter.forall(action) + end +end + +active class Main + def main() : unit + (new Pif)!foo() + end +end diff --git a/src/tests/encore/regressions/18.out b/src/tests/encore/regressions/18.out new file mode 100644 index 000000000..f599e28b8 --- /dev/null +++ b/src/tests/encore/regressions/18.out @@ -0,0 +1 @@ +10 From 226ac079e2ff55e7209a56000f8b2500990dc50b Mon Sep 17 00:00:00 2001 From: supercooldave Date: Mon, 24 Apr 2017 12:40:32 +0200 Subject: [PATCH 03/18] Commented to explain code (#788) --- src/front/ModuleExpander.hs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/front/ModuleExpander.hs b/src/front/ModuleExpander.hs index fad253df0..fe98fb3dc 100644 --- a/src/front/ModuleExpander.hs +++ b/src/front/ModuleExpander.hs @@ -17,7 +17,7 @@ import Types(setRefSourceFile, setRefNamespace) import SystemUtils import Control.Monad import Control.Arrow((&&&)) -import System.Directory(doesFileExist) +import System.Directory(doesFileExist, makeAbsolute) import Data.Map.Strict(Map) import qualified Data.Map.Strict as Map import Data.List @@ -121,9 +121,14 @@ buildModulePath (NSExplicit ns) = findSource :: [FilePath] -> FilePath -> ImportDecl -> IO FilePath findSource importDirs sourceDir Import{itarget} = do let modulePath = buildModulePath itarget - sources = nub $ - sourceDir modulePath : - map ( modulePath) importDirs + imports = map ( modulePath) importDirs + sourceModulePath = sourceDir modulePath + expandedSourceModulePath <- makeAbsolute $ sourceModulePath + let sources = if expandedSourceModulePath `elem` imports then + -- if directory of target is in imports, remove it to avoid ambiguous import error + nub $ imports + else + nub $ sourceModulePath : imports candidates <- filterM doesFileExist sources case candidates of [] -> abort $ "Module " ++ show itarget ++ From 18b070a27268fb9b1b5ecd34abdd555bbc571e15 Mon Sep 17 00:00:00 2001 From: Elias Castegren Date: Wed, 3 May 2017 09:24:13 +0200 Subject: [PATCH 04/18] Disallow silently capturing an active this as a passive reference (#789) * Disallow silently capturing an active this as a passive reference Before this commit, in an `active` class, you could use `this` to access fields or (synchronously) call methods inside a closure. Because the mode of `this` is `active`, which is safe, the mode of the closure would allow it to be shared, leading to potential data-races. This commit changes an `active` `this` to a `local` variable if it is used for synchronous accesses. This forces the `local` mode on a closure containing e.g. `this.foo()`. There are also some improved error messages and a small check for when a required `var` field is provided as a `val` field. Fixes #781. * Dumb down C-type name generation For C readability reasons, when a mode was available for a class, the C name would include the name (e.g. `_enc__read_String_String_t`). This breaks having multiple views of `this` in an active class, so this commit removes it (writing `class` instead of the mode). --- modules/standard/String.enc | 8 ++--- src/back/CodeGen/CCodeNames.hs | 4 +-- src/ir/AST/AST.hs | 3 ++ src/tests/encore/basic/valFields.enc | 2 +- .../capabilities/activeThisFieldCapture.enc | 14 ++++++++ .../capabilities/activeThisFieldCapture.fail | 1 + .../capabilities/activeThisMethodCapture.enc | 18 ++++++++++ .../capabilities/activeThisMethodCapture.fail | 1 + src/tests/encore/par/each.enc | 5 +-- src/tests/encore/regressions/18.enc | 4 +-- src/tests/encore/traits/varRequire.enc | 7 ++++ src/tests/encore/traits/varRequire.fail | 1 + src/types/Typechecker/TypeError.hs | 33 +++++++++++++------ src/types/Typechecker/Typechecker.hs | 21 +++++++++--- src/types/Types.hs | 2 ++ 15 files changed, 98 insertions(+), 26 deletions(-) create mode 100644 src/tests/encore/capabilities/activeThisFieldCapture.enc create mode 100644 src/tests/encore/capabilities/activeThisFieldCapture.fail create mode 100644 src/tests/encore/capabilities/activeThisMethodCapture.enc create mode 100644 src/tests/encore/capabilities/activeThisMethodCapture.fail create mode 100644 src/tests/encore/traits/varRequire.enc create mode 100644 src/tests/encore/traits/varRequire.fail diff --git a/modules/standard/String.enc b/modules/standard/String.enc index 4bdc46cb5..9bd5bf21e 100644 --- a/modules/standard/String.enc +++ b/modules/standard/String.enc @@ -11,11 +11,11 @@ BODY // This function is called in the very beginning of the program to // build an array containing the arguments of the program. array_t *_init_argv(pony_ctx_t** ctx, size_t argc, char **argv) { - array_t *arr = array_mk(ctx, argc, &_enc__read_String_String_type); + array_t *arr = array_mk(ctx, argc, &_enc__class_String_String_type); for(int i = 0; i < argc; i++) { - _enc__read_String_String_t* s = - encore_alloc(*ctx, sizeof(_enc__read_String_String_t)); - s->_enc__self_type = &_enc__read_String_String_type; + _enc__class_String_String_t* s = + encore_alloc(*ctx, sizeof(_enc__class_String_String_t)); + s->_enc__self_type = &_enc__class_String_String_type; _enc__method_String_String_init(ctx, s, NULL, argv[i]); array_set(arr, i, (encore_arg_t){.p = s}); } diff --git a/src/back/CodeGen/CCodeNames.hs b/src/back/CodeGen/CCodeNames.hs index 9f351b42e..d942087e8 100644 --- a/src/back/CodeGen/CCodeNames.hs +++ b/src/back/CodeGen/CCodeNames.hs @@ -404,9 +404,7 @@ oneWayMsgId cls mname = typeNamePrefix :: Ty.Type -> String typeNamePrefix ref | Ty.isTraitType ref = encoreName "trait" qname - | Ty.isRefAtomType ref = if Ty.isModeless ref - then encoreName "passive" qname - else encoreName (showModeOf ref) qname + | Ty.isRefAtomType ref = encoreName "class" qname | otherwise = error $ "type_name_prefix Type '" ++ show ref ++ "' isnt reference type!" where diff --git a/src/ir/AST/AST.hs b/src/ir/AST/AST.hs index 9e7762dc7..232fe384d 100644 --- a/src/ir/AST/AST.hs +++ b/src/ir/AST/AST.hs @@ -429,6 +429,9 @@ instance HasMeta FieldDecl where isValField :: FieldDecl -> Bool isValField = (== Val) . fmut +isVarField :: FieldDecl -> Bool +isVarField = (== Var) . fmut + data ParamDecl = Param { pmeta :: Meta ParamDecl, pmut :: Mutability, diff --git a/src/tests/encore/basic/valFields.enc b/src/tests/encore/basic/valFields.enc index 558c9a096..38bed0bef 100644 --- a/src/tests/encore/basic/valFields.enc +++ b/src/tests/encore/basic/valFields.enc @@ -39,7 +39,7 @@ local class Link[v] : Mappable[v](next) end end local class Stack[v] : Push[v] - val top : Mappable[v] + var top : Mappable[v] def init() : unit this.top = new Sentinel[v]() end diff --git a/src/tests/encore/capabilities/activeThisFieldCapture.enc b/src/tests/encore/capabilities/activeThisFieldCapture.enc new file mode 100644 index 000000000..3238e0cca --- /dev/null +++ b/src/tests/encore/capabilities/activeThisFieldCapture.enc @@ -0,0 +1,14 @@ +active class C + var f : int + def foo() : (() -> int) + fun () => this.f + end +end + +active class Main + def main(args : [String]) : unit + val c = new C + val f = get(c!foo()) + f() + end +end \ No newline at end of file diff --git a/src/tests/encore/capabilities/activeThisFieldCapture.fail b/src/tests/encore/capabilities/activeThisFieldCapture.fail new file mode 100644 index 000000000..3cc5fd16b --- /dev/null +++ b/src/tests/encore/capabilities/activeThisFieldCapture.fail @@ -0,0 +1 @@ +Closure of type 'local (() -> int)' captures local state and cannot be used as type '() -> int' diff --git a/src/tests/encore/capabilities/activeThisMethodCapture.enc b/src/tests/encore/capabilities/activeThisMethodCapture.enc new file mode 100644 index 000000000..860ddc533 --- /dev/null +++ b/src/tests/encore/capabilities/activeThisMethodCapture.enc @@ -0,0 +1,18 @@ +active class C + var f : int + def foo() : (() -> int) + fun () => this.f() + end + def f() : int + this.f = 0 + 42 + end +end + +active class Main + def main(args : [String]) : unit + val c = new C + val f = get(c!foo()) + f() + end +end \ No newline at end of file diff --git a/src/tests/encore/capabilities/activeThisMethodCapture.fail b/src/tests/encore/capabilities/activeThisMethodCapture.fail new file mode 100644 index 000000000..3cc5fd16b --- /dev/null +++ b/src/tests/encore/capabilities/activeThisMethodCapture.fail @@ -0,0 +1 @@ +Closure of type 'local (() -> int)' captures local state and cannot be used as type '() -> int' diff --git a/src/tests/encore/par/each.enc b/src/tests/encore/par/each.enc index 5b4a11888..a97c6e91d 100644 --- a/src/tests/encore/par/each.enc +++ b/src/tests/encore/par/each.enc @@ -26,11 +26,12 @@ active class Main def test_setting_array() : unit let arr = presetArray(this.size) + check_arr = this.check_arr in each(arr) >> fun (i : int) - (this.check_arr)(i) = true + check_arr(i) = true i - end >> fun (i : int) => assertTrue((this.check_arr)(i)) + end >> fun (i : int) => assertTrue(check_arr(i)) end end diff --git a/src/tests/encore/regressions/18.enc b/src/tests/encore/regressions/18.enc index d0132e9ce..e3e3a254e 100644 --- a/src/tests/encore/regressions/18.enc +++ b/src/tests/encore/regressions/18.enc @@ -2,8 +2,8 @@ local class Filter def cancel(i : int) : unit println(i) end - - def forall(f : int -> unit) : unit + + def forall(f : local((int) -> unit)) : unit f(10) end end diff --git a/src/tests/encore/traits/varRequire.enc b/src/tests/encore/traits/varRequire.enc new file mode 100644 index 000000000..8b62542aa --- /dev/null +++ b/src/tests/encore/traits/varRequire.enc @@ -0,0 +1,7 @@ +trait T + require var f : int +end + +class C : local T + val f : int +end \ No newline at end of file diff --git a/src/tests/encore/traits/varRequire.fail b/src/tests/encore/traits/varRequire.fail new file mode 100644 index 000000000..26b3607e4 --- /dev/null +++ b/src/tests/encore/traits/varRequire.fail @@ -0,0 +1 @@ +Trait 'T' requires field 'val f : int' to be mutable diff --git a/src/types/Typechecker/TypeError.hs b/src/types/Typechecker/TypeError.hs index 4f3cc080d..7fabfcd81 100644 --- a/src/types/Typechecker/TypeError.hs +++ b/src/types/Typechecker/TypeError.hs @@ -274,6 +274,7 @@ data Error = | TypeVariableAndVariableCommonNameError [Name] | UnionMethodAmbiguityError Type Name | MalformedUnionTypeError Type Type + | RequiredFieldMutabilityError Type FieldDecl | ProvidingTraitFootprintError Type Type Name [FieldDecl] | TypeArgumentInferenceError Expr Type | AmbiguousTypeError Type [Type] @@ -307,7 +308,7 @@ data Error = | NonSafeInReadContextError Type Type | NonSafeInExtendedReadTraitError Type Name Type | ProvidingToReadTraitError Type Type Name - | SubordinateReturnError Name + | SubordinateReturnError Name Type | SubordinateArgumentError Expr | SubordinateFieldError Name | ThreadLocalFieldError Type @@ -315,7 +316,7 @@ data Error = | ThreadLocalArgumentError Expr | PolymorphicArgumentSendError Expr Type | PolymorphicReturnError Name Type - | ThreadLocalReturnError Name + | ThreadLocalReturnError Name Type | MalformedConjunctionError Type Type Type | CannotUnpackError Type | CannotInferUnpackingError Type @@ -601,8 +602,13 @@ instance Show Error where printf ("Null valued expression cannot have type '%s' " ++ "(must have reference type)") (show ty) show (TypeMismatchError actual expected) = - printf "Type '%s' does not match expected type '%s'" - (show actual) (show expected) + if isArrowType actual && isArrowType expected && + actual `withModeOf` expected == expected + then printf ("Closure of type '%s' captures %s state and cannot " ++ + "be used as type '%s'") + (show actual) (showModeOf actual) (show expected) + else printf "Type '%s' does not match expected type '%s'" + (show actual) (show expected) show (TypeWithCapabilityMismatchError actual cap expected) = printf "Type '%s' with capability '%s' does not match expected type '%s'%s" (show actual) (show cap) (show expected) pointer @@ -662,6 +668,9 @@ instance Show Error where | otherwise = error msg msg = "TypeError.hs: " ++ show call ++ " is not a function or method call" + show (RequiredFieldMutabilityError requirer field) = + printf "Trait '%s' requires field '%s' to be mutable" + (getId requirer) (show field) show (ProvidingTraitFootprintError provider requirer mname fields) = printf ("Trait '%s' cannot provide method '%s' to %s.\n" ++ "'%s' can mutate fields that are marked immutable in '%s':\n%s") @@ -764,10 +773,12 @@ instance Show Error where show (ProvidingToReadTraitError provider requirer mname) = printf "Non-read trait '%s' cannot provide method '%s' to read trait '%s'" (getId provider) (show mname) (getId requirer) - show (SubordinateReturnError name) = - printf ("Method '%s' returns a subordinate capability and cannot " ++ + show (SubordinateReturnError name ty) = + printf ("Method '%s' returns a %s and cannot " ++ "be called from outside of its aggregate") - (show name) + (show name) (if isArrowType ty + then "closure that captures subordinate state" + else "subordinate capability") show (SubordinateArgumentError arg) = if isArrowType (getType arg) then printf ("Closure '%s' captures subordinate state " ++ @@ -796,10 +807,12 @@ instance Show Error where else printf ("Cannot pass actor local argument '%s' " ++ "to another active object") (show (ppSugared arg)) - show (ThreadLocalReturnError name) = - printf ("Method '%s' returns a local capability and cannot " ++ + show (ThreadLocalReturnError name ty) = + printf ("Method '%s' returns a %s and cannot " ++ "be called by a different active object") - (show name) + (show name) (if isArrowType ty + then "closure that captures local state" + else "local capability") show (PolymorphicArgumentSendError arg ty) = printf ("Cannot pass value of '%s' between active objects. " ++ "Its type is polymorphic so it may not be safe to share.\n" ++ diff --git a/src/types/Typechecker/Typechecker.hs b/src/types/Typechecker/Typechecker.hs index 1f59707d1..a30b4c64a 100644 --- a/src/types/Typechecker/Typechecker.hs +++ b/src/types/Typechecker/Typechecker.hs @@ -211,6 +211,9 @@ meetRequiredFields cFields trait = do isSub <- cFieldType `subtypeOf` expected unless (cFieldType == expected) $ tcError $ RequiredFieldMismatchError cField expected trait isSub + when (isVarField expField) $ + unless (isVarField cField) $ + tcError $ RequiredFieldMutabilityError trait cField noOverlapFields :: Type -> Maybe TraitComposition -> TypecheckM () noOverlapFields cname composition = @@ -693,7 +696,12 @@ instance Checkable Expr where (header, calledType) <- findMethodWithCalledType targetType (name mcall) matchArgumentLength targetType header (args mcall) - let eTarget' = setType calledType eTarget + + isActive <- isActiveType targetType + let eTarget' = if isThisAccess eTarget && + isActive && isMethodCall mcall + then setType (makeLocal calledType) eTarget + else setType calledType eTarget typeParams = htypeparams header argTypes = map ptype $ hparams header resultType = htype header @@ -1367,13 +1375,18 @@ instance Checkable Expr where doTypecheck fAcc@(FieldAccess {target, name}) = do eTarget <- typecheck target let targetType = AST.getType eTarget + isActive <- isActiveType targetType + let accessedType = if isThisAccess eTarget && isActive + then makeLocal targetType + else targetType + eTarget' = setType accessedType eTarget unless (isThisAccess target || isPassiveClassType targetType && not (isModeless targetType)) $ tcError $ CannotReadFieldError eTarget fdecl <- findField targetType name let ty = ftype fdecl checkFieldEncapsulation name eTarget ty - return $ setType ty fAcc {target = eTarget} + return $ setType ty fAcc {target = eTarget'} -- E |- lhs : t -- isLval(lhs) @@ -1897,7 +1910,7 @@ checkSubordinateReturn name returnType targetType = do targetIsEncaps <- isEncapsulatedType targetType when subordReturn $ unless targetIsEncaps $ - tcError $ SubordinateReturnError name + tcError $ SubordinateReturnError name returnType checkSubordinateArgs :: [Expr] -> Type -> TypecheckM () checkSubordinateArgs args targetType = do @@ -1944,7 +1957,7 @@ checkLocalReturn name returnType targetType = when (isActiveSingleType targetType) $ do localReturn <- isLocalType returnType when localReturn $ - tcError $ ThreadLocalReturnError name + tcError $ ThreadLocalReturnError name returnType let nonSharable = find nonSharableTypeVar $ typeComponents returnType when (isJust nonSharable) $ diff --git a/src/types/Types.hs b/src/types/Types.hs index c2e0dbac5..91c3d4632 100644 --- a/src/types/Types.hs +++ b/src/types/Types.hs @@ -680,6 +680,8 @@ withModeOf sink source , info <- refInfo iType , mode <- mode $ refInfo (inner source) = sink{inner = iType{refInfo = info{mode}}} + | isArrowType sink && isArrowType source + , modes <- getModes source = applyInner (\i -> i{modes}) sink | otherwise = error $ "Types.hs: Can't transfer modes from " ++ showWithKind source ++ " to " ++ showWithKind sink From 63c1876183ac682b3a28becc82dd3df7cb864b64 Mon Sep 17 00:00:00 2001 From: Elias Castegren Date: Wed, 3 May 2017 09:32:03 +0200 Subject: [PATCH 05/18] Add range information to parsed nodes (#790) * Add range information to parsed nodes This commit extends the source position to include the range of positions of an Encore AST-node. Before, when parsing an expression, e.g. `(2,3)`, we would only know where the expression began. Now we also have information on where the expression ends (in this example 5 characters after the beginning). This is not visible to the programmer in any way, but is integral for the upcoming editor mode support. * Refactoring --- src/front/ModuleExpander.hs | 8 +- src/ir/AST/AST.hs | 8 +- src/ir/AST/Desugarer.hs | 10 +- src/ir/AST/Meta.hs | 46 ++- src/parser/Parser/Parser.hs | 439 +++++++++++++++++------------ src/types/Typechecker/TypeError.hs | 9 +- 6 files changed, 315 insertions(+), 205 deletions(-) diff --git a/src/front/ModuleExpander.hs b/src/front/ModuleExpander.hs index fe98fb3dc..69aaeaa4a 100644 --- a/src/front/ModuleExpander.hs +++ b/src/front/ModuleExpander.hs @@ -47,7 +47,7 @@ shortenPrelude preludePaths source = stdLib source = [lib "String", lib "Std"] where - lib s = Import{imeta = meta $ initialPos source + lib s = Import{imeta = meta $ newPos (initialPos source) ,itarget = explicitNamespace [Name s] ,isource = Nothing ,iqualified = False @@ -122,13 +122,13 @@ findSource :: [FilePath] -> FilePath -> ImportDecl -> IO FilePath findSource importDirs sourceDir Import{itarget} = do let modulePath = buildModulePath itarget imports = map ( modulePath) importDirs - sourceModulePath = sourceDir modulePath + sourceModulePath = sourceDir modulePath expandedSourceModulePath <- makeAbsolute $ sourceModulePath let sources = if expandedSourceModulePath `elem` imports then -- if directory of target is in imports, remove it to avoid ambiguous import error nub $ imports - else - nub $ sourceModulePath : imports + else + nub $ sourceModulePath : imports candidates <- filterM doesFileExist sources case candidates of [] -> abort $ "Module " ++ show itarget ++ diff --git a/src/ir/AST/AST.hs b/src/ir/AST/AST.hs index 232fe384d..a4bbe2728 100644 --- a/src/ir/AST/AST.hs +++ b/src/ir/AST/AST.hs @@ -40,9 +40,15 @@ class Show a => HasMeta a where setMeta :: a -> Meta a -> a - getPos :: a -> SourcePos + getPos :: a -> Position getPos = Meta.getPos . getMeta + setEndPos :: SourcePos -> a -> a + setEndPos end x = + let oldMeta = getMeta x + newMeta = Meta.setEndPos end oldMeta + in setMeta x newMeta + getType :: a -> Type getType = Meta.getType . getMeta diff --git a/src/ir/AST/Desugarer.hs b/src/ir/AST/Desugarer.hs index 0e073a6a4..7b79c7e7a 100644 --- a/src/ir/AST/Desugarer.hs +++ b/src/ir/AST/Desugarer.hs @@ -54,9 +54,9 @@ desugarProgram p@(Program{traits, classes, functions}) = ,hname=Name "suspend" ,htype=unitType ,hparams=[]} - pmeta = Meta.meta (Meta.sourcePos cmeta) - emeta = Meta.meta (Meta.sourcePos cmeta) - mmeta = Meta.meta (Meta.sourcePos cmeta) + pmeta = Meta.meta (Meta.getPos cmeta) + emeta = Meta.meta (Meta.getPos cmeta) + mmeta = Meta.meta (Meta.getPos cmeta) desugarClass c@(Class{cmethods}) | isPassive c || isShared c = c{cmethods = map desugarMethod cmethods} @@ -117,7 +117,7 @@ selfSugar :: Expr -> Expr selfSugar e = setSugared e e cloneMeta :: Meta.Meta Expr -> Meta.Meta Expr -cloneMeta m = Meta.meta (Meta.sourcePos m) +cloneMeta m = Meta.meta (Meta.getPos m) -- | A @MiniLet@ that has not been taken care of by @desugar@ is -- dead and can be removed. @@ -243,7 +243,7 @@ desugar IfThen{emeta, cond, thn} = IfThenElse{emeta ,cond ,thn - ,els = Skip (Meta.meta (Meta.sourcePos (cloneMeta emeta))) + ,els = Skip (Meta.meta (Meta.getPos (cloneMeta emeta))) } desugar Unless{emeta, cond = originalCond, thn} = diff --git a/src/ir/AST/Meta.hs b/src/ir/AST/Meta.hs index e453ad95f..a75f84e26 100644 --- a/src/ir/AST/Meta.hs +++ b/src/ir/AST/Meta.hs @@ -15,23 +15,41 @@ data MetaInfo = Closure {metaId :: String} | MetaArrow {metaArrow :: Type} deriving (Eq, Show) -data Meta a = Meta {sourcePos :: SourcePos, +data Position = SingletonPos {startPos :: SourcePos} + | RangePos {startPos :: SourcePos, + endPos :: SourcePos} + deriving (Eq) + +instance Show Position where + -- TODO: If we ever want to print ranges, this should be updated + show = showSourcePos . startPos + +newPos :: SourcePos -> Position +newPos = SingletonPos + +data Meta a = Meta {position :: Position, metaType :: Maybe Type, sugared :: Maybe a, captureStatus :: Maybe CaptureStatus, isPattern :: Bool, - statement :: Bool, + statement :: Bool, metaInfo :: Maybe MetaInfo} deriving (Eq, Show) -meta :: SourcePos -> Meta a -meta pos = Meta {sourcePos = pos - ,metaType = Nothing - ,sugared = Nothing - ,statement = False - ,captureStatus = Nothing - ,isPattern = False - ,metaInfo = Nothing} - +meta :: Position -> Meta a +meta position = + Meta {position + ,metaType = Nothing + ,sugared = Nothing + ,statement = False + ,captureStatus = Nothing + ,isPattern = False + ,metaInfo = Nothing} + +setEndPos :: SourcePos -> Meta a -> Meta a +setEndPos endPos m@Meta{position} = + m{position = RangePos{startPos = startPos position, endPos}} + +showSourcePos :: SourcePos -> String showSourcePos pos = let line = unPos (sourceLine pos) col = unPos (sourceColumn pos) @@ -39,10 +57,10 @@ showSourcePos pos = in printf "%s (line %d, column %d)" (show file) line col showPos :: Meta a -> String -showPos = showSourcePos . sourcePos +showPos = showSourcePos . startPos . position -getPos :: Meta a -> SourcePos -getPos = sourcePos +getPos :: Meta a -> Position +getPos = position setType :: Type -> Meta a -> Meta a setType newType m = m {metaType = Just newType} diff --git a/src/parser/Parser/Parser.hs b/src/parser/Parser/Parser.hs index e63b3d025..659e5408e 100644 --- a/src/parser/Parser/Parser.hs +++ b/src/parser/Parser/Parser.hs @@ -26,7 +26,8 @@ import Control.Arrow (first, (&&&)) import Identifiers hiding(namespace) import Types hiding(refType) import AST.AST -import AST.Meta hiding(Closure, Async, getPos) +import AST.Meta hiding(Closure, Async, getPos, setEndPos) +import qualified AST.Meta as Meta(setEndPos) -- | 'parseEncoreProgram' @path@ @code@ assumes @path@ is the path -- to the file being parsed and will produce an AST for @code@, @@ -169,7 +170,12 @@ blockedConstruct header = do constructor <- header parseBody constructor atLevel indent $ reserved "end" - return block + returnWithEnd block + +returnWithEnd :: HasMeta a => a -> EncParser a +returnWithEnd x = do + end <- getPosition + return $ setEndPos end x -- | These parsers use the lexer above and are the smallest -- building blocks of the whole parser. @@ -469,22 +475,23 @@ program = do moduleDecl :: EncParser ModuleDecl moduleDecl = option NoModule $ lineFold $ \sc' -> do - modmeta <- meta <$> getPosition + modmeta <- meta . newPos <$> getPosition reserved "module" lookAhead upperChar modname <- Name <$> identifier modexports <- optional $ folded parens sc' ((Name <$> identifier) `sepEndBy` comma) - return Module{modmeta - ,modname - ,modexports - } + returnWithEnd + Module{modmeta + ,modname + ,modexports + } importdecl :: EncParser ImportDecl importdecl = lineFold $ \sc' -> do indent <- L.indentLevel - imeta <- meta <$> getPosition + imeta <- meta . newPos <$> getPosition reserved "import" iqualified <- option False $ reserved "qualified" >> return True itarget <- explicitNamespace <$> modulePath @@ -498,14 +505,15 @@ importdecl = try sc' reserved "hiding" folded parens sc' ((Name <$> identifier) `sepEndBy` comma) - return Import{imeta - ,itarget - ,iqualified - ,iselect - ,ihiding - ,ialias - ,isource = Nothing - } + returnWithEnd + Import{imeta + ,itarget + ,iqualified + ,iselect + ,ihiding + ,ialias + ,isource = Nothing + } embedTL :: EncParser EmbedTL embedTL = do @@ -514,13 +522,13 @@ embedTL = do (try (do string "EMBED" header <- manyTill anyChar $ try $ do {spaceChar; string "BODY"} code <- manyTill anyChar $ try $ do {spaceChar; reserved "END"} - return $ EmbedTL (meta pos) header code + return $ EmbedTL (meta (newPos pos)) header code ) <|> try (do string "EMBED" header <- manyTill anyChar $ try $ do {spaceChar; reserved "END"} - return $ EmbedTL (meta pos) header "" + return $ EmbedTL (meta (newPos pos)) header "" ) <|> - (return $ EmbedTL (meta pos) "" "")) + (return $ EmbedTL (meta (newPos pos)) "" "")) optionalTypeParameters = option [] (brackets $ commaSep1 modedTypeVar) where @@ -531,7 +539,7 @@ optionalTypeParameters = option [] (brackets $ commaSep1 modedTypeVar) typedef :: EncParser Typedef typedef = do - typedefmeta <- meta <$> getPosition + typedefmeta <- meta . newPos <$> getPosition indent <- L.indentLevel reserved "typedef" name <- lookAhead upperChar >> identifier @@ -540,7 +548,8 @@ typedef = do typedeftype <- typ <|> (hidden nl >> indented indent typ) let typedefdef = setRefNamespace emptyNamespace $ typeSynonym name params typedeftype - return Typedef{typedefmeta, typedefdef} + returnWithEnd + Typedef{typedefmeta, typedefdef} functionHeader :: EncParser FunctionHeader functionHeader = @@ -550,13 +559,14 @@ functionHeader = hparams <- folded parens sc' (commaSep paramDecl) colon htype <- typ - return Header{hmodifiers = [] - ,kind = NonStreaming - ,htypeparams - ,hname - ,hparams - ,htype - } + return + Header{hmodifiers = [] + ,kind = NonStreaming + ,htypeparams + ,hname + ,hparams + ,htype + } streamMethodHeader :: EncParser FunctionHeader streamMethodHeader = do @@ -579,7 +589,8 @@ localFunction = do funIndent <- L.indentLevel fun <- funHeaderAndBody atLevel funIndent $ reserved "end" - return fun + returnWithEnd + fun globalFunction :: EncParser Function globalFunction = do @@ -589,12 +600,12 @@ globalFunction = do funlocals <- option [] $ atLevel funIndent whereClause atLevel funIndent $ reserved "end" - - return fun{funlocals} + returnWithEnd + fun{funlocals} funHeaderAndBody = indentBlock $ do - funmeta <- meta <$> getPosition + funmeta <- meta . newPos <$> getPosition reserved "fun" funheader <- functionHeader alignedExpressions (buildFun funmeta funheader) @@ -648,7 +659,7 @@ traitDecl :: EncParser TraitDecl traitDecl = do tIndent <- L.indentLevel tdecl <- indentBlock $ do - tmeta <- meta <$> getPosition + tmeta <- meta . newPos <$> getPosition setMode <- option id mode reserved "trait" ident <- lookAhead upperChar >> identifier @@ -659,7 +670,8 @@ traitDecl = do traitAttribute -- TODO: tlocals <- option [] $ atLevel tIndent whereClause atLevel tIndent $ reserved "end" - return tdecl + returnWithEnd + tdecl where traitAttribute = label "requirement" (TReqAttribute <$> requirement) @@ -739,7 +751,7 @@ classDecl :: EncParser ClassDecl classDecl = do cIndent <- L.indentLevel cdecl <- indentBlock $ do - cmeta <- meta <$> getPosition + cmeta <- meta . newPos <$> getPosition setMode <- try $ do m <- option id mode reserved "class" @@ -753,7 +765,8 @@ classDecl = do classAttribute -- TODO: clocals <- option [] $ atLevel cIndent whereClause atLevel cIndent $ reserved "end" - return cdecl + returnWithEnd + cdecl where classAttribute = (FieldAttribute <$> fieldDecl) <|> (MethodAttribute <$> methodDecl) @@ -774,26 +787,28 @@ mutModifier = (reserved "var" >> return Var) <|> (reserved "val" >> return Val) fieldDecl :: EncParser FieldDecl -fieldDecl = do fmeta <- meta <$> getPosition +fieldDecl = do fmeta <- meta . newPos <$> getPosition fmut <- mutModifier fname <- Name <$> identifier colon ftype <- typ - return Field{fmeta - ,fmut - ,fname - ,ftype} + returnWithEnd + Field{fmeta + ,fmut + ,fname + ,ftype} paramDecl :: EncParser ParamDecl paramDecl = do - pmeta <- meta <$> getPosition + pmeta <- meta . newPos <$> getPosition pmut <- option Val $ (reserved "var" >> return Var) <|> (reserved "val" >> return Val) pname <- Name <$> identifier colon ptype <- typ - return Param{pmeta, pmut, pname, ptype} + returnWithEnd + Param{pmeta, pmut, pname, ptype} patternParamDecl :: EncParser (Expr, Type) patternParamDecl = do @@ -809,11 +824,12 @@ methodDecl = do mlocals <- option [] $ atLevel mIndent whereClause atLevel mIndent $ reserved "end" - return mtd{mlocals} + returnWithEnd + mtd{mlocals} where methodHeaderAndBody = indentBlock $ do - mmeta <- meta <$> getPosition + mmeta <- meta . newPos <$> getPosition mheader <- do reserved "def" modifiers <- many modifier setHeaderModifier modifiers <$> functionHeader @@ -849,7 +865,7 @@ matchClause = do (needsEnd, clause) <- indentBlock $ do reserved "case" mcpattern <- expression <|> dontCare - guardMeta <- meta <$> getPosition + guardMeta <- meta . newPos <$> getPosition mcguard <- option (BTrue guardMeta) guard reservedOp "=>" lineClause mcpattern mcguard <|> blockClause mcpattern mcguard @@ -868,9 +884,10 @@ matchClause = do ,mchandler = makeBody body })) dontCare = do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition symbol "_" - return VarAccess{emeta, qname = qName "_"} + returnWithEnd + VarAccess{emeta, qname = qName "_"} expression :: EncParser Expr expression = makeExprParser expr opTable @@ -900,73 +917,89 @@ expression = makeExprParser expr opTable op "/=" DIV_EQUALS] ] + opRange emeta = do + end <- getPosition + return $ Meta.setEndPos end emeta + textualPrefix s operator = - Prefix (try(do pos <- getPosition + Prefix (try(do emeta <- meta . newPos <$> getPosition reserved s - return (Unary (meta pos) operator))) + emeta' <- opRange emeta + return (Unary emeta' operator))) prefix s operator = - Prefix (do pos <- getPosition + Prefix (do emeta <- meta . newPos <$> getPosition reservedOp s - return (Unary (meta pos) operator)) + emeta' <- opRange emeta + return (Unary emeta' operator)) op s binop = - InfixL (do pos <- getPosition + InfixL (do emeta <- meta . newPos <$> getPosition withLinebreaks $ reservedOp s - return (Binop (meta pos) binop)) + emeta' <- opRange emeta + return (Binop emeta' binop)) arrayAccess = - Postfix (do pos <- getPosition + Postfix (do emeta <- meta . newPos <$> getPosition index <- parens expression - return (\target -> ArrayAccess{emeta = meta pos + emeta' <- opRange emeta + return (\target -> ArrayAccess{emeta = emeta' ,target ,index })) consume = - Prefix (do pos <- getPosition + Prefix (do emeta <- meta . newPos <$> getPosition reserved "consume" - return (Consume (meta pos))) + emeta' <- opRange emeta + return (Consume emeta')) typedExpression = - Postfix (do pos <- getPosition + Postfix (do emeta <- meta . newPos <$> getPosition withLinebreaks colon - t <- typ - return (\e -> TypedExpr (meta pos) e t)) + ty <- typ + emeta' <- opRange emeta + return (\body -> TypedExpr{emeta = emeta' + ,body + ,ty})) messageSend = - Postfix (do pos <- getPosition + Postfix (do emeta <- meta . newPos <$> getPosition withLinebreaks bang name <- Name <$> identifier typeArguments <- option [] (try . brackets $ commaSep typ) args <- parens arguments - let msgSend opt target = MessageSend {emeta = meta pos - ,typeArguments - ,target - ,name - ,args} - return $ msgSend False) + emeta' <- opRange emeta + return (\target -> MessageSend{emeta = emeta' + ,typeArguments + ,target + ,name + ,args})) singleLineTask = Prefix (do notFollowedBy (reserved "async" >> nl) - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition reserved "async" - return (Async emeta)) + emeta' <- opRange emeta + return (Async emeta')) chain = - - InfixL (do pos <- getPosition + InfixL (do emeta <- meta . newPos <$> getPosition withLinebreaks $ reservedOp "~~>" - return (FutureChain (meta pos))) + emeta' <- opRange emeta + return (FutureChain emeta')) partySequence = - InfixL (do pos <- getPosition ; - reservedOp ">>" ; - return (PartySeq (meta pos))) + InfixL (do emeta <- meta . newPos <$> getPosition + reservedOp ">>" + emeta' <- opRange emeta + return (PartySeq emeta')) partyParallel = - InfixL (do pos <- getPosition ; - reservedOp "|||" ; - return (PartyPar (meta pos))) + InfixL (do emeta <- meta . newPos <$> getPosition + reservedOp "|||" + emeta' <- opRange emeta + return (PartyPar emeta')) assignment = - InfixR (do pos <- getPosition ; - reservedOp "=" ; - return (Assign (meta pos))) + InfixR (do emeta <- meta . newPos <$> getPosition + reservedOp "=" + emeta' <- opRange emeta + return (Assign emeta')) -- Elias: I don't know why the first 'notFollowedBy nl' needed, -- but it improves error messages @@ -1009,7 +1042,7 @@ expr = notFollowedBy nl >> embed = do indent <- L.indentLevel startLine <- sourceLine <$> getPosition - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition reserved "EMBED" ty <- label "parenthesized type" $ parens typ @@ -1022,13 +1055,14 @@ expr = notFollowedBy nl >> else atLevel indent $ reserved "END" when (null embedded) $ fail "EMBED block cannot be empty" - return Embed{emeta, ty, embedded} + returnWithEnd + Embed{emeta, ty, embedded} where cAndEncore :: EncParser (String, Expr) cAndEncore = (do notFollowedBy $ reserved "END" code <- c - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition e <- option Skip{emeta} (try $ encoreEscaped expression) return (code, e)) @@ -1051,12 +1085,12 @@ expr = notFollowedBy nl >> longerPath pos root <|> return root where tupled = do - pos <- getPosition + emeta <- meta . newPos <$> getPosition args <- parens (expression `sepBy` comma) case args of - [] -> return $ Skip (meta pos) + [] -> returnWithEnd $ Skip emeta [e] -> return e - _ -> return $ Tuple (meta pos) args + _ -> returnWithEnd $ Tuple emeta args qualifiedVarOrFun = do qx <- qualifiedVarAccess @@ -1067,17 +1101,19 @@ expr = notFollowedBy nl >> functionOrCall x <|> return x qualifiedVarAccess = do - pos <- getPosition + emeta <- meta . newPos <$> getPosition ns <- explicitNamespace <$> modulePath dot x <- identifier - let qx = setNamespace ns (qName x) - return $ VarAccess (meta pos) qx + let qname = setNamespace ns (qName x) + returnWithEnd + VarAccess{emeta, qname} varAccess = do - pos <- getPosition - id <- (do reserved "this"; return "this") <|> identifier - return $ VarAccess (meta pos) (qName id) + emeta <- meta . newPos <$> getPosition + qname <- qName <$> ((do reserved "this"; return "this") <|> identifier) + returnWithEnd + VarAccess{emeta, qname} functionOrCall VarAccess{emeta, qname} = do optTypeArgs <- option [] (try . brackets $ commaSep typ) @@ -1087,44 +1123,61 @@ expr = notFollowedBy nl >> call emeta optTypeArgs qname <|> return (FunctionAsValue emeta optTypeArgs qname) - call emeta typeArgs name = do + call emeta typeArguments qname = do args <- parens arguments - return $ FunctionCall emeta typeArgs name args + returnWithEnd + FunctionCall{emeta + ,typeArguments + ,qname + ,args} longerPath pos root = do first <- pathComponent rest <- many $ try pathComponent - return $ foldl (buildPath pos) root (first:rest) + returnWithEnd $ + foldl (buildPath pos) root (first:rest) pathComponent = do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition try comparmentAcc <|> try varOrCallFunction <|> optionalAccessBang emeta <|> optionalAccessDot emeta where optionalAccessBang emeta = do reservedOp "?!" m <- varAccess >>= functionCall - return $ Optional emeta (QuestionBang m) + returnWithEnd + Optional{emeta + ,optTag = QuestionBang m + } optionalAccessDot emeta = do reservedOp "?." var <- varOrCall - return $ Optional emeta (QuestionDot var) + returnWithEnd + Optional{emeta + ,optTag = QuestionDot var + } comparmentAcc = dot >> compartmentAccess varOrCallFunction = dot >> varOrCall compartmentAccess = do - pos <- getPosition - n <- lexeme L.integer - return $ IntLiteral (meta pos) (fromInteger n) + emeta <- meta . newPos <$> getPosition + intLit <- fromInteger <$> lexeme L.integer + returnWithEnd + IntLiteral{emeta, intLit} varOrCall = do x <- varAccess functionCall x <|> return x functionCall VarAccess{emeta, qname} = do - typeParams <- option [] (try . brackets $ commaSep typ) + typeArguments <- option [] (try . brackets $ commaSep typ) args <- parens arguments - return $ FunctionCall emeta typeParams qname args + returnWithEnd + FunctionCall{emeta + ,typeArguments + ,qname + ,args + } buildPath _ target o@Optional {emeta, optTag = QuestionBang f@(FunctionCall {})} = o {optTag = QuestionBang $ MessageSend emeta (typeArguments f) target (qnlocal $ qname f) (args f)} @@ -1136,19 +1189,19 @@ expr = notFollowedBy nl >> o { optTag = QuestionDot $ FieldAccess emeta target (qnlocal qname) } buildPath pos target (VarAccess{qname}) = - FieldAccess (meta pos) target (qnlocal qname) + FieldAccess (meta $ newPos pos) target (qnlocal qname) buildPath pos target (FunctionCall{qname, args, typeArguments}) = - MethodCall (meta pos) typeArguments target (qnlocal qname) args + MethodCall (meta $ newPos pos) typeArguments target (qnlocal qname) args buildPath pos target (IntLiteral {intLit}) = - TupleAccess (meta pos) target intLit + TupleAccess (meta $ newPos pos) target intLit letExpression = do indent <- L.indentLevel letLine <- sourceLine <$> getPosition (needsEnd, letExpr) <- indentBlock $ do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition decls <- indentBlock $ do reserved "let" inlineDecls indent <|> indentedDecls indent @@ -1164,7 +1217,8 @@ expr = notFollowedBy nl >> nonInlineLet indent emeta decls when needsEnd $ atLevel indent $ reserved "end" - return letExpr + returnWithEnd + letExpr where inlineDecls letIndent = do notFollowedBy nl @@ -1205,31 +1259,35 @@ expr = notFollowedBy nl >> sequence = singleLineBlock <|> multiLineBlock singleLineBlock = do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition eseq <- braces (expression `sepEndBy1` semi) - return Seq{emeta, eseq} + returnWithEnd + Seq{emeta, eseq} multiLineBlock = do indent <- L.indentLevel block <- indentBlock $ do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition reserved "do" alignedExpressions (return . Seq emeta) doBlock indent block <|> doWhile indent block doBlock indent block = do atLevel indent $ reserved "end" - return block + returnWithEnd + block doWhile indent body = do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition atLevel indent $ reserved "while" cond <- expression - return DoWhile{emeta, cond, body} + returnWithEnd + DoWhile{emeta, cond, body} miniLet = do indent <- L.indentLevel - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition mutability <- mutModifier (x, val) <- varDecl indent - return MiniLet{emeta, mutability, decl = (x, val)} + returnWithEnd + MiniLet{emeta, mutability, decl = (x, val)} ifExpression = do indent <- L.indentLevel @@ -1243,7 +1301,7 @@ expr = notFollowedBy nl >> ifWithSimpleCond indent ifLine head = do notFollowedBy (head >> nl) indentBlock $ do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition atLevel indent head cond <- expression thenLine <- sourceLine <$> getPosition @@ -1253,7 +1311,7 @@ expr = notFollowedBy nl >> inlineIfThen emeta cond <|> nonInlineIfThen indent emeta cond ifWithComplexCond indent head = do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition head nl cond <- indented indent expression @@ -1275,7 +1333,8 @@ expr = notFollowedBy nl >> if endLine == ifLine then reserved "end" else atLevel indent $ reserved "end" - return ifThen + returnWithEnd + ifThen ifThenElse indent ifLine ifThen = do elseLine <- sourceLine <$> getPosition @@ -1284,7 +1343,8 @@ expr = notFollowedBy nl >> reserved "else" els <- expression reserved "end" - return $ extendIfThen ifThen els + returnWithEnd $ + extendIfThen ifThen els else finalElse indent ifThen <|> elseIf indent ifThen @@ -1307,39 +1367,40 @@ expr = notFollowedBy nl >> atLevel indent $ reserved "else" parseBody (extendIfThen ifThen) atLevel indent $ reserved "end" - return result + returnWithEnd + result extendIfThen IfThen{emeta, cond, thn} els = IfThenElse{emeta, cond, thn, els} unlessIf = blockedConstruct $ do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition reserved "unless" cond <- expression reserved "then" return $ \thn -> Unless{emeta, cond, thn} for = blockedConstruct $ do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition reserved "for" name <- Name <$> identifier reservedOp "<-" src <- expression - stepMeta <- meta <$> getPosition + stepMeta <- meta . newPos <$> getPosition step <- option (IntLiteral stepMeta 1) (do {reserved "by"; expression}) reserved "do" return $ \body -> For{emeta, name, src, step, body} while = blockedConstruct $ do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition reserved "while" cond <- expression reserved "do" return $ \body -> While{emeta, cond, body} repeat = blockedConstruct $ do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition reserved "repeat" name <- Name <$> identifier reservedOp "<-" @@ -1350,16 +1411,17 @@ expr = notFollowedBy nl >> match = do indent <- L.indentLevel theMatch <- indentBlock $ do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition reserved "match" arg <- expression reserved "with" return $ L.IndentSome Nothing (return . Match emeta arg) matchClause atLevel indent $ reserved "end" - return theMatch + returnWithEnd + theMatch borrow = blockedConstruct $ do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition reserved "borrow" target <- expression reserved "as" @@ -1368,43 +1430,49 @@ expr = notFollowedBy nl >> return $ \body -> Borrow{emeta, target, name, body} yield = do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition reserved "yield" val <- expression - return Yield{emeta, val} + returnWithEnd + Yield{emeta, val} isEos = do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition reserved "eos" target <- expression - return IsEos{emeta, target} + returnWithEnd + IsEos{emeta, target} eos = do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition reserved "eos" - return Eos{emeta} + returnWithEnd + Eos{emeta} break = do - pos <- getPosition + emeta <- meta . newPos <$> getPosition reserved "break" - return $ Break (meta pos) + returnWithEnd + Break {emeta} continue = do - pos <- getPosition + emeta <- meta . newPos <$> getPosition reserved "continue" - return $ Continue (meta pos) + returnWithEnd + Continue{emeta} forward = do - pos <- getPosition + emeta <- meta . newPos <$> getPosition reserved "forward" - expr <- parens expression - return $ Forward (meta pos) expr + forwardExpr <- parens expression + returnWithEnd + Forward{emeta, forwardExpr} closure = do indent <- L.indentLevel funLine <- sourceLine <$> getPosition (withEnd, clos) <- indentBlock $ do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition reserved "fun" eparams <- parens (commaSep paramDecl) mty <- optional (colon >> typ) @@ -1412,7 +1480,8 @@ expr = notFollowedBy nl >> blockClosure emeta eparams mty when withEnd $ atLevel indent $ reserved "end" - return clos + returnWithEnd + clos singleLineClosure emeta eparams mty = do reservedOp "=>" body <- expression @@ -1427,34 +1496,38 @@ expr = notFollowedBy nl >> }) blockedTask = blockedConstruct $ do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition reserved "async" return $ \body -> Async{emeta, body} arraySize = do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition bar target <- expression bar - return ArraySize{emeta, target} + returnWithEnd + ArraySize{emeta, target} nullLiteral = do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition reserved "null" - return Null{emeta} + returnWithEnd + Null{emeta} true = do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition reserved "true" - return BTrue{emeta} + returnWithEnd + BTrue{emeta} false = do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition reserved "false" - return BFalse{emeta} + returnWithEnd + BFalse{emeta} new = do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition reserved "new" notFollowedBy mode ty <- typ @@ -1462,65 +1535,79 @@ expr = notFollowedBy nl >> where newWithoutInit emeta ty = do notFollowedBy (symbol "(") - return New{emeta, ty} + returnWithEnd + New{emeta, ty} newWithInit emeta ty = do args <- parens arguments - return NewWithInit{emeta, ty, args} + returnWithEnd + NewWithInit{emeta, ty, args} stringLit = do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition stringLit <- stringLiteral - return StringLiteral{emeta, stringLit} + returnWithEnd + StringLiteral{emeta, stringLit} charLit = do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition charLit <- charLiteral - return CharLiteral{emeta, charLit} + returnWithEnd + CharLiteral{emeta, charLit} int = do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition n <- L.integer kind <- do hidden (symbol "u") <|> hidden (symbol "U") return UIntLiteral <|> (hspace >> return IntLiteral) - return $ kind emeta (fromInteger n) + returnWithEnd $ + kind emeta (fromInteger n) real = do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition realLit <- float - return RealLiteral{emeta, realLit} + returnWithEnd + RealLiteral{emeta, realLit} - explicitReturn = do pos <- getPosition - reserved "return" - expr <- option (Skip (meta pos)) expression - return $ Return (meta pos) expr + explicitReturn = do + emeta <- meta . newPos <$> getPosition + reserved "return" + pos <- getPosition + val <- option (Skip (meta $ newPos pos)) expression + returnWithEnd + Return{emeta, val} - bracketed = - lineFold $ \sc' -> + bracketed = do + result <- lineFold $ \sc' -> folded brackets sc' (rangeOrArray <|> empty) + returnWithEnd + result where empty = do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition lookAhead (symbol "]") return ArrayLiteral{emeta, args = []} rangeOrArray = do - emeta <- meta <$> getPosition + emeta <- meta . newPos <$> getPosition first <- expression range emeta first <|> arrayLit emeta first range emeta start = do dotdot stop <- expression - stepMeta <- meta <$> getPosition + stepMeta <- meta . newPos <$> getPosition step <- option (IntLiteral stepMeta 1) (reserved "by" >> expression) + end <- getPosition return RangeLiteral{emeta, start, stop, step} arrayLit emeta first = longerArray <|> singletonArray where - singletonArray = + singletonArray = do + end <- getPosition return ArrayLiteral{emeta, args = [first]} longerArray = do notFollowedBy (symbol "]") comma rest <- commaSep1 expression + end <- getPosition return ArrayLiteral{emeta, args = first:rest} diff --git a/src/types/Typechecker/TypeError.hs b/src/types/Typechecker/TypeError.hs index 7fabfcd81..36f230163 100644 --- a/src/types/Typechecker/TypeError.hs +++ b/src/types/Typechecker/TypeError.hs @@ -21,7 +21,6 @@ module Typechecker.TypeError (Backtrace ) where import Text.PrettyPrint -import Text.Megaparsec(SourcePos) import Data.Maybe import Data.List import Data.Char @@ -31,7 +30,7 @@ import Identifiers import Types import AST.AST hiding (showWithKind) import AST.PrettyPrinter -import AST.Meta(showSourcePos) +import AST.Meta(Position) data BacktraceNode = BTFunction Name Type | BTTrait Type @@ -75,7 +74,7 @@ instance Show BacktraceNode where show (BTImport ns) = concat ["In import of module '", show ns, "'"] -type Backtrace = [(SourcePos, BacktraceNode)] +type Backtrace = [(Position, BacktraceNode)] emptyBT :: Backtrace emptyBT = [] @@ -187,7 +186,7 @@ instance Show TCError where show err ++ "\n" show (TCError err bt@((pos, _):_)) = " *** Error during typechecking *** \n" ++ - showSourcePos pos ++ "\n" ++ + show pos ++ "\n" ++ show err ++ "\n" ++ concatMap showBT (reduceBT bt) where @@ -928,7 +927,7 @@ instance Show TCWarning where "Warning:\n" ++ show w show (TCWarning ((pos, _):_) w) = - "Warning at " ++ showSourcePos pos ++ ":\n" ++ + "Warning at " ++ show pos ++ ":\n" ++ show w data Warning = StringDeprecatedWarning From bb9ca31b2c080367690a74d74cf44c05ee5956f1 Mon Sep 17 00:00:00 2001 From: Elias Castegren Date: Thu, 4 May 2017 07:07:37 +0200 Subject: [PATCH 06/18] Refactoring of prematurely merged #790 (#796) Reacted to @kikofernandez' comments from #790. All in all, 56 lines shorter! --- src/ir/AST/AST.hs | 8 + src/parser/Parser/Parser.hs | 382 +++++++++++++++--------------------- 2 files changed, 167 insertions(+), 223 deletions(-) diff --git a/src/ir/AST/AST.hs b/src/ir/AST/AST.hs index a4bbe2728..2bdb032ad 100644 --- a/src/ir/AST/AST.hs +++ b/src/ir/AST/AST.hs @@ -91,6 +91,14 @@ data EmbedTL = EmbedTL { etlbody :: String } deriving (Show) +instance HasMeta EmbedTL where + getMeta = etlmeta + + setMeta etl etlmeta = etl{etlmeta} + + setType ty i = + error "AST.hs: Cannot set the type of a EmbedTL" + data ModuleDecl = Module { modmeta :: Meta ModuleDecl, modname :: Name, diff --git a/src/parser/Parser/Parser.hs b/src/parser/Parser/Parser.hs index 659e5408e..8e57d6cce 100644 --- a/src/parser/Parser/Parser.hs +++ b/src/parser/Parser/Parser.hs @@ -177,6 +177,9 @@ returnWithEnd x = do end <- getPosition return $ setEndPos end x +buildMeta :: HasMeta a => EncParser (Meta a) +buildMeta = meta . newPos <$> getPosition + -- | These parsers use the lexer above and are the smallest -- building blocks of the whole parser. reservedNames = @@ -475,7 +478,7 @@ program = do moduleDecl :: EncParser ModuleDecl moduleDecl = option NoModule $ lineFold $ \sc' -> do - modmeta <- meta . newPos <$> getPosition + modmeta <- buildMeta reserved "module" lookAhead upperChar modname <- Name <$> identifier @@ -491,7 +494,7 @@ importdecl :: EncParser ImportDecl importdecl = lineFold $ \sc' -> do indent <- L.indentLevel - imeta <- meta . newPos <$> getPosition + imeta <- buildMeta reserved "import" iqualified <- option False $ reserved "qualified" >> return True itarget <- explicitNamespace <$> modulePath @@ -518,17 +521,25 @@ importdecl = embedTL :: EncParser EmbedTL embedTL = do -- TODO: Make sure BODY and END are not indented - pos <- getPosition - (try (do string "EMBED" - header <- manyTill anyChar $ try $ do {spaceChar; string "BODY"} - code <- manyTill anyChar $ try $ do {spaceChar; reserved "END"} - return $ EmbedTL (meta (newPos pos)) header code - ) <|> - try (do string "EMBED" - header <- manyTill anyChar $ try $ do {spaceChar; reserved "END"} - return $ EmbedTL (meta (newPos pos)) header "" - ) <|> - (return $ EmbedTL (meta (newPos pos)) "" "")) + etlmeta <- buildMeta + try (embedWithBody etlmeta) <|> try (embedWithoutBody etlmeta) <|> + return EmbedTL{etlmeta + ,etlheader = "" + ,etlbody = ""} + where + embedWithBody etlmeta = do + string "EMBED" + etlheader <- manyTill anyChar $ try $ do {spaceChar; string "BODY"} + etlbody <- manyTill anyChar $ try $ do {spaceChar; reserved "END"} + return EmbedTL{etlmeta + ,etlheader + ,etlbody} + embedWithoutBody etlmeta = do + string "EMBED" + etlheader <- manyTill anyChar $ try $ do {spaceChar; reserved "END"} + return EmbedTL{etlmeta + ,etlheader + ,etlbody = ""} optionalTypeParameters = option [] (brackets $ commaSep1 modedTypeVar) where @@ -539,7 +550,7 @@ optionalTypeParameters = option [] (brackets $ commaSep1 modedTypeVar) typedef :: EncParser Typedef typedef = do - typedefmeta <- meta . newPos <$> getPosition + typedefmeta <- buildMeta indent <- L.indentLevel reserved "typedef" name <- lookAhead upperChar >> identifier @@ -548,8 +559,7 @@ typedef = do typedeftype <- typ <|> (hidden nl >> indented indent typ) let typedefdef = setRefNamespace emptyNamespace $ typeSynonym name params typedeftype - returnWithEnd - Typedef{typedefmeta, typedefdef} + returnWithEnd Typedef{typedefmeta, typedefdef} functionHeader :: EncParser FunctionHeader functionHeader = @@ -589,8 +599,7 @@ localFunction = do funIndent <- L.indentLevel fun <- funHeaderAndBody atLevel funIndent $ reserved "end" - returnWithEnd - fun + returnWithEnd fun globalFunction :: EncParser Function globalFunction = do @@ -600,12 +609,11 @@ globalFunction = do funlocals <- option [] $ atLevel funIndent whereClause atLevel funIndent $ reserved "end" - returnWithEnd - fun{funlocals} + returnWithEnd fun{funlocals} funHeaderAndBody = indentBlock $ do - funmeta <- meta . newPos <$> getPosition + funmeta <- buildMeta reserved "fun" funheader <- functionHeader alignedExpressions (buildFun funmeta funheader) @@ -659,7 +667,7 @@ traitDecl :: EncParser TraitDecl traitDecl = do tIndent <- L.indentLevel tdecl <- indentBlock $ do - tmeta <- meta . newPos <$> getPosition + tmeta <- buildMeta setMode <- option id mode reserved "trait" ident <- lookAhead upperChar >> identifier @@ -670,8 +678,7 @@ traitDecl = do traitAttribute -- TODO: tlocals <- option [] $ atLevel tIndent whereClause atLevel tIndent $ reserved "end" - returnWithEnd - tdecl + returnWithEnd tdecl where traitAttribute = label "requirement" (TReqAttribute <$> requirement) @@ -751,7 +758,7 @@ classDecl :: EncParser ClassDecl classDecl = do cIndent <- L.indentLevel cdecl <- indentBlock $ do - cmeta <- meta . newPos <$> getPosition + cmeta <- buildMeta setMode <- try $ do m <- option id mode reserved "class" @@ -765,8 +772,7 @@ classDecl = do classAttribute -- TODO: clocals <- option [] $ atLevel cIndent whereClause atLevel cIndent $ reserved "end" - returnWithEnd - cdecl + returnWithEnd cdecl where classAttribute = (FieldAttribute <$> fieldDecl) <|> (MethodAttribute <$> methodDecl) @@ -787,28 +793,24 @@ mutModifier = (reserved "var" >> return Var) <|> (reserved "val" >> return Val) fieldDecl :: EncParser FieldDecl -fieldDecl = do fmeta <- meta . newPos <$> getPosition - fmut <- mutModifier - fname <- Name <$> identifier - colon - ftype <- typ - returnWithEnd - Field{fmeta - ,fmut - ,fname - ,ftype} +fieldDecl = do + fmeta <- buildMeta + fmut <- mutModifier + fname <- Name <$> identifier + colon + ftype <- typ + returnWithEnd Field{fmeta, fmut, fname, ftype} paramDecl :: EncParser ParamDecl paramDecl = do - pmeta <- meta . newPos <$> getPosition + pmeta <- buildMeta pmut <- option Val $ (reserved "var" >> return Var) <|> (reserved "val" >> return Val) pname <- Name <$> identifier colon ptype <- typ - returnWithEnd - Param{pmeta, pmut, pname, ptype} + returnWithEnd Param{pmeta, pmut, pname, ptype} patternParamDecl :: EncParser (Expr, Type) patternParamDecl = do @@ -824,12 +826,11 @@ methodDecl = do mlocals <- option [] $ atLevel mIndent whereClause atLevel mIndent $ reserved "end" - returnWithEnd - mtd{mlocals} + returnWithEnd mtd{mlocals} where methodHeaderAndBody = indentBlock $ do - mmeta <- meta . newPos <$> getPosition + mmeta <- buildMeta mheader <- do reserved "def" modifiers <- many modifier setHeaderModifier modifiers <$> functionHeader @@ -865,7 +866,7 @@ matchClause = do (needsEnd, clause) <- indentBlock $ do reserved "case" mcpattern <- expression <|> dontCare - guardMeta <- meta . newPos <$> getPosition + guardMeta <- buildMeta mcguard <- option (BTrue guardMeta) guard reservedOp "=>" lineClause mcpattern mcguard <|> blockClause mcpattern mcguard @@ -884,10 +885,9 @@ matchClause = do ,mchandler = makeBody body })) dontCare = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta symbol "_" - returnWithEnd - VarAccess{emeta, qname = qName "_"} + returnWithEnd VarAccess{emeta, qname = qName "_"} expression :: EncParser Expr expression = makeExprParser expr opTable @@ -917,57 +917,47 @@ expression = makeExprParser expr opTable op "/=" DIV_EQUALS] ] - opRange emeta = do + withEnd p = do + emeta <- buildMeta + x <- p end <- getPosition - return $ Meta.setEndPos end emeta + return (Meta.setEndPos end emeta, x) textualPrefix s operator = - Prefix (try(do emeta <- meta . newPos <$> getPosition - reserved s - emeta' <- opRange emeta - return (Unary emeta' operator))) + Prefix (try(do (emeta, _) <- withEnd $ reserved s + return (Unary emeta operator))) prefix s operator = - Prefix (do emeta <- meta . newPos <$> getPosition - reservedOp s - emeta' <- opRange emeta - return (Unary emeta' operator)) + Prefix (do (emeta, _) <- withEnd $ reservedOp s + return (Unary emeta operator)) op s binop = - InfixL (do emeta <- meta . newPos <$> getPosition - withLinebreaks $ reservedOp s - emeta' <- opRange emeta - return (Binop emeta' binop)) + InfixL (do (emeta, _) <- withEnd . withLinebreaks $ reservedOp s + return (Binop emeta binop)) arrayAccess = - Postfix (do emeta <- meta . newPos <$> getPosition - index <- parens expression - emeta' <- opRange emeta - return (\target -> ArrayAccess{emeta = emeta' + Postfix (do (emeta, index) <- withEnd $ parens expression + return (\target -> ArrayAccess{emeta ,target ,index })) consume = - Prefix (do emeta <- meta . newPos <$> getPosition - reserved "consume" - emeta' <- opRange emeta - return (Consume emeta')) + Prefix (do (emeta, _) <- withEnd $ reserved "consume" + return (Consume emeta)) typedExpression = - Postfix (do emeta <- meta . newPos <$> getPosition - withLinebreaks colon - ty <- typ - emeta' <- opRange emeta - return (\body -> TypedExpr{emeta = emeta' + Postfix (do (emeta, ty) <- withEnd (withLinebreaks colon >> typ) + return (\body -> TypedExpr{emeta ,body ,ty})) messageSend = - Postfix (do emeta <- meta . newPos <$> getPosition - withLinebreaks bang - name <- Name <$> identifier - typeArguments <- option [] (try . brackets $ commaSep typ) - args <- parens arguments - emeta' <- opRange emeta - return (\target -> MessageSend{emeta = emeta' + Postfix (do (emeta, (name, typeArguments, args)) <- withEnd $ do + withLinebreaks bang + name <- Name <$> identifier + typeArguments <- + option [] (try . brackets $ commaSep typ) + args <- parens arguments + return (name, typeArguments, args) + return (\target -> MessageSend{emeta ,typeArguments ,target ,name @@ -975,31 +965,21 @@ expression = makeExprParser expr opTable singleLineTask = Prefix (do notFollowedBy (reserved "async" >> nl) - emeta <- meta . newPos <$> getPosition - reserved "async" - emeta' <- opRange emeta - return (Async emeta')) + (emeta, _) <- withEnd $ reserved "async" + return (Async emeta)) chain = - InfixL (do emeta <- meta . newPos <$> getPosition - withLinebreaks $ reservedOp "~~>" - emeta' <- opRange emeta - return (FutureChain emeta')) + InfixL (do (emeta, _) <- withEnd . withLinebreaks $ reservedOp "~~>" + return (FutureChain emeta)) partySequence = - InfixL (do emeta <- meta . newPos <$> getPosition - reservedOp ">>" - emeta' <- opRange emeta - return (PartySeq emeta')) + InfixL (do (emeta, _) <- withEnd $ reservedOp ">>" + return (PartySeq emeta)) partyParallel = - InfixL (do emeta <- meta . newPos <$> getPosition - reservedOp "|||" - emeta' <- opRange emeta - return (PartyPar emeta')) + InfixL (do (emeta, _) <- withEnd $ reservedOp "|||" + return (PartyPar emeta)) assignment = - InfixR (do emeta <- meta . newPos <$> getPosition - reservedOp "=" - emeta' <- opRange emeta - return (Assign emeta')) + InfixR (do (emeta, _) <- withEnd $ reservedOp "=" + return (Assign emeta)) -- Elias: I don't know why the first 'notFollowedBy nl' needed, -- but it improves error messages @@ -1042,7 +1022,7 @@ expr = notFollowedBy nl >> embed = do indent <- L.indentLevel startLine <- sourceLine <$> getPosition - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta reserved "EMBED" ty <- label "parenthesized type" $ parens typ @@ -1055,14 +1035,13 @@ expr = notFollowedBy nl >> else atLevel indent $ reserved "END" when (null embedded) $ fail "EMBED block cannot be empty" - returnWithEnd - Embed{emeta, ty, embedded} + returnWithEnd Embed{emeta, ty, embedded} where cAndEncore :: EncParser (String, Expr) cAndEncore = (do notFollowedBy $ reserved "END" code <- c - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta e <- option Skip{emeta} (try $ encoreEscaped expression) return (code, e)) @@ -1085,12 +1064,12 @@ expr = notFollowedBy nl >> longerPath pos root <|> return root where tupled = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta args <- parens (expression `sepBy` comma) case args of - [] -> returnWithEnd $ Skip emeta + [] -> returnWithEnd Skip{emeta} [e] -> return e - _ -> returnWithEnd $ Tuple emeta args + _ -> returnWithEnd Tuple{emeta, args} qualifiedVarOrFun = do qx <- qualifiedVarAccess @@ -1101,19 +1080,17 @@ expr = notFollowedBy nl >> functionOrCall x <|> return x qualifiedVarAccess = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta ns <- explicitNamespace <$> modulePath dot x <- identifier let qname = setNamespace ns (qName x) - returnWithEnd - VarAccess{emeta, qname} + returnWithEnd VarAccess{emeta, qname} varAccess = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta qname <- qName <$> ((do reserved "this"; return "this") <|> identifier) - returnWithEnd - VarAccess{emeta, qname} + returnWithEnd VarAccess{emeta, qname} functionOrCall VarAccess{emeta, qname} = do optTypeArgs <- option [] (try . brackets $ commaSep typ) @@ -1125,11 +1102,7 @@ expr = notFollowedBy nl >> call emeta typeArguments qname = do args <- parens arguments - returnWithEnd - FunctionCall{emeta - ,typeArguments - ,qname - ,args} + returnWithEnd FunctionCall{emeta, typeArguments, qname, args} longerPath pos root = do first <- pathComponent @@ -1138,32 +1111,26 @@ expr = notFollowedBy nl >> foldl (buildPath pos) root (first:rest) pathComponent = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta try comparmentAcc <|> try varOrCallFunction <|> optionalAccessBang emeta <|> optionalAccessDot emeta where optionalAccessBang emeta = do reservedOp "?!" m <- varAccess >>= functionCall - returnWithEnd - Optional{emeta - ,optTag = QuestionBang m - } + returnWithEnd Optional{emeta, optTag = QuestionBang m} optionalAccessDot emeta = do reservedOp "?." var <- varOrCall returnWithEnd - Optional{emeta - ,optTag = QuestionDot var - } + Optional{emeta, optTag = QuestionDot var} comparmentAcc = dot >> compartmentAccess varOrCallFunction = dot >> varOrCall compartmentAccess = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta intLit <- fromInteger <$> lexeme L.integer - returnWithEnd - IntLiteral{emeta, intLit} + returnWithEnd IntLiteral{emeta, intLit} varOrCall = do x <- varAccess @@ -1172,12 +1139,7 @@ expr = notFollowedBy nl >> functionCall VarAccess{emeta, qname} = do typeArguments <- option [] (try . brackets $ commaSep typ) args <- parens arguments - returnWithEnd - FunctionCall{emeta - ,typeArguments - ,qname - ,args - } + returnWithEnd FunctionCall{emeta, typeArguments, qname, args} buildPath _ target o@Optional {emeta, optTag = QuestionBang f@(FunctionCall {})} = o {optTag = QuestionBang $ MessageSend emeta (typeArguments f) target (qnlocal $ qname f) (args f)} @@ -1201,7 +1163,7 @@ expr = notFollowedBy nl >> indent <- L.indentLevel letLine <- sourceLine <$> getPosition (needsEnd, letExpr) <- indentBlock $ do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta decls <- indentBlock $ do reserved "let" inlineDecls indent <|> indentedDecls indent @@ -1217,8 +1179,7 @@ expr = notFollowedBy nl >> nonInlineLet indent emeta decls when needsEnd $ atLevel indent $ reserved "end" - returnWithEnd - letExpr + returnWithEnd letExpr where inlineDecls letIndent = do notFollowedBy nl @@ -1259,35 +1220,31 @@ expr = notFollowedBy nl >> sequence = singleLineBlock <|> multiLineBlock singleLineBlock = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta eseq <- braces (expression `sepEndBy1` semi) - returnWithEnd - Seq{emeta, eseq} + returnWithEnd Seq{emeta, eseq} multiLineBlock = do indent <- L.indentLevel block <- indentBlock $ do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta reserved "do" alignedExpressions (return . Seq emeta) doBlock indent block <|> doWhile indent block doBlock indent block = do atLevel indent $ reserved "end" - returnWithEnd - block + returnWithEnd block doWhile indent body = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta atLevel indent $ reserved "while" cond <- expression - returnWithEnd - DoWhile{emeta, cond, body} + returnWithEnd DoWhile{emeta, cond, body} miniLet = do indent <- L.indentLevel - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta mutability <- mutModifier (x, val) <- varDecl indent - returnWithEnd - MiniLet{emeta, mutability, decl = (x, val)} + returnWithEnd MiniLet{emeta, mutability, decl = (x, val)} ifExpression = do indent <- L.indentLevel @@ -1301,7 +1258,7 @@ expr = notFollowedBy nl >> ifWithSimpleCond indent ifLine head = do notFollowedBy (head >> nl) indentBlock $ do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta atLevel indent head cond <- expression thenLine <- sourceLine <$> getPosition @@ -1311,7 +1268,7 @@ expr = notFollowedBy nl >> inlineIfThen emeta cond <|> nonInlineIfThen indent emeta cond ifWithComplexCond indent head = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta head nl cond <- indented indent expression @@ -1333,8 +1290,7 @@ expr = notFollowedBy nl >> if endLine == ifLine then reserved "end" else atLevel indent $ reserved "end" - returnWithEnd - ifThen + returnWithEnd ifThen ifThenElse indent ifLine ifThen = do elseLine <- sourceLine <$> getPosition @@ -1367,40 +1323,39 @@ expr = notFollowedBy nl >> atLevel indent $ reserved "else" parseBody (extendIfThen ifThen) atLevel indent $ reserved "end" - returnWithEnd - result + returnWithEnd result extendIfThen IfThen{emeta, cond, thn} els = IfThenElse{emeta, cond, thn, els} unlessIf = blockedConstruct $ do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta reserved "unless" cond <- expression reserved "then" return $ \thn -> Unless{emeta, cond, thn} for = blockedConstruct $ do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta reserved "for" name <- Name <$> identifier reservedOp "<-" src <- expression - stepMeta <- meta . newPos <$> getPosition + stepMeta <- buildMeta step <- option (IntLiteral stepMeta 1) (do {reserved "by"; expression}) reserved "do" return $ \body -> For{emeta, name, src, step, body} while = blockedConstruct $ do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta reserved "while" cond <- expression reserved "do" return $ \body -> While{emeta, cond, body} repeat = blockedConstruct $ do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta reserved "repeat" name <- Name <$> identifier reservedOp "<-" @@ -1411,17 +1366,16 @@ expr = notFollowedBy nl >> match = do indent <- L.indentLevel theMatch <- indentBlock $ do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta reserved "match" arg <- expression reserved "with" return $ L.IndentSome Nothing (return . Match emeta arg) matchClause atLevel indent $ reserved "end" - returnWithEnd - theMatch + returnWithEnd theMatch borrow = blockedConstruct $ do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta reserved "borrow" target <- expression reserved "as" @@ -1430,49 +1384,43 @@ expr = notFollowedBy nl >> return $ \body -> Borrow{emeta, target, name, body} yield = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta reserved "yield" val <- expression - returnWithEnd - Yield{emeta, val} + returnWithEnd Yield{emeta, val} isEos = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta reserved "eos" target <- expression - returnWithEnd - IsEos{emeta, target} + returnWithEnd IsEos{emeta, target} eos = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta reserved "eos" - returnWithEnd - Eos{emeta} + returnWithEnd Eos{emeta} break = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta reserved "break" - returnWithEnd - Break {emeta} + returnWithEnd Break {emeta} continue = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta reserved "continue" - returnWithEnd - Continue{emeta} + returnWithEnd Continue{emeta} forward = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta reserved "forward" forwardExpr <- parens expression - returnWithEnd - Forward{emeta, forwardExpr} + returnWithEnd Forward{emeta, forwardExpr} closure = do indent <- L.indentLevel funLine <- sourceLine <$> getPosition (withEnd, clos) <- indentBlock $ do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta reserved "fun" eparams <- parens (commaSep paramDecl) mty <- optional (colon >> typ) @@ -1480,8 +1428,7 @@ expr = notFollowedBy nl >> blockClosure emeta eparams mty when withEnd $ atLevel indent $ reserved "end" - returnWithEnd - clos + returnWithEnd clos singleLineClosure emeta eparams mty = do reservedOp "=>" body <- expression @@ -1496,38 +1443,34 @@ expr = notFollowedBy nl >> }) blockedTask = blockedConstruct $ do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta reserved "async" return $ \body -> Async{emeta, body} arraySize = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta bar target <- expression bar - returnWithEnd - ArraySize{emeta, target} + returnWithEnd ArraySize{emeta, target} nullLiteral = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta reserved "null" - returnWithEnd - Null{emeta} + returnWithEnd Null{emeta} true = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta reserved "true" - returnWithEnd - BTrue{emeta} + returnWithEnd BTrue{emeta} false = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta reserved "false" - returnWithEnd - BFalse{emeta} + returnWithEnd BFalse{emeta} new = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta reserved "new" notFollowedBy mode ty <- typ @@ -1535,27 +1478,23 @@ expr = notFollowedBy nl >> where newWithoutInit emeta ty = do notFollowedBy (symbol "(") - returnWithEnd - New{emeta, ty} + returnWithEnd New{emeta, ty} newWithInit emeta ty = do args <- parens arguments - returnWithEnd - NewWithInit{emeta, ty, args} + returnWithEnd NewWithInit{emeta, ty, args} stringLit = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta stringLit <- stringLiteral - returnWithEnd - StringLiteral{emeta, stringLit} + returnWithEnd StringLiteral{emeta, stringLit} charLit = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta charLit <- charLiteral - returnWithEnd - CharLiteral{emeta, charLit} + returnWithEnd CharLiteral{emeta, charLit} int = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta n <- L.integer kind <- do hidden (symbol "u") <|> hidden (symbol "U") return UIntLiteral @@ -1564,38 +1503,35 @@ expr = notFollowedBy nl >> kind emeta (fromInteger n) real = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta realLit <- float - returnWithEnd - RealLiteral{emeta, realLit} + returnWithEnd RealLiteral{emeta, realLit} explicitReturn = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta reserved "return" pos <- getPosition val <- option (Skip (meta $ newPos pos)) expression - returnWithEnd - Return{emeta, val} + returnWithEnd Return{emeta, val} bracketed = do result <- lineFold $ \sc' -> folded brackets sc' (rangeOrArray <|> empty) - returnWithEnd - result + returnWithEnd result where empty = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta lookAhead (symbol "]") return ArrayLiteral{emeta, args = []} rangeOrArray = do - emeta <- meta . newPos <$> getPosition + emeta <- buildMeta first <- expression range emeta first <|> arrayLit emeta first range emeta start = do dotdot stop <- expression - stepMeta <- meta . newPos <$> getPosition + stepMeta <- buildMeta step <- option (IntLiteral stepMeta 1) (reserved "by" >> expression) end <- getPosition From 1c1caec94741d883cae7ac3967b269519515f046 Mon Sep 17 00:00:00 2001 From: Huu-Phuc Vo Date: Thu, 4 May 2017 12:05:00 +0200 Subject: [PATCH 07/18] Extended forward (#784) * Added forward for future chain case * Grouped common functions * Added error message * Added forward on preexisting future * Clean up code * Fixed and Added one testcase for preexisting future * Temp commit, could be removed * Generate id function * Rebase and keep forward(arg) code comments * Add minor fix * Add minor fix * Added forward on preexisting future * Fixed forward(id(arg)) and removed commented codes * Fixed general cases in Optimiser * Clean up code * Renamed function, removed bad codes, and added more testcases * Revised new test, removed unsed error message * Removed unused function * Refactored code * Changed to static future_chain, renamed function --- src/back/CodeGen/CCodeNames.hs | 5 +- src/back/CodeGen/Context.hs | 6 +- src/back/CodeGen/Expr.hs | 66 +++++++++++++------ src/opt/Optimizer/Optimizer.hs | 30 ++++++++- src/runtime/future/future.c | 24 +++++-- src/runtime/future/future.h | 3 + src/tests/encore/forward/forwardChaining.enc | 5 +- src/tests/encore/forward/forwardChaining.fail | 1 - src/tests/encore/forward/forwardChaining.out | 1 + src/tests/encore/forward/forwardCoverage.enc | 34 ++++++++++ src/tests/encore/forward/forwardCoverage.out | 3 + .../encore/forward/forwardFieldAccess.enc | 26 ++++++++ .../encore/forward/forwardFieldAccess.out | 1 + .../encore/forward/forwardInnerForward.enc | 31 +++++++++ .../encore/forward/forwardInnerForward.out | 2 + .../encore/forward/forwardNestedForward.enc | 29 ++++++++ .../encore/forward/forwardNestedForward.out | 1 + .../forward/forwardPreexistingFuture.enc | 6 +- .../forward/forwardPreexistingFuture.fail | 1 - .../forward/forwardPreexistingFuture.out | 1 + .../forward/forwardPreexistingFutureChain.enc | 19 ++++++ .../forward/forwardPreexistingFutureChain.out | 1 + .../forwardPreexistingFutureFunctionCall.enc | 19 ++++++ .../forwardPreexistingFutureFunctionCall.out | 1 + src/types/Typechecker/TypeError.hs | 5 +- src/types/Typechecker/Typechecker.hs | 2 - 26 files changed, 284 insertions(+), 39 deletions(-) delete mode 100644 src/tests/encore/forward/forwardChaining.fail create mode 100644 src/tests/encore/forward/forwardChaining.out create mode 100644 src/tests/encore/forward/forwardCoverage.enc create mode 100644 src/tests/encore/forward/forwardCoverage.out create mode 100644 src/tests/encore/forward/forwardFieldAccess.enc create mode 100644 src/tests/encore/forward/forwardFieldAccess.out create mode 100644 src/tests/encore/forward/forwardInnerForward.enc create mode 100644 src/tests/encore/forward/forwardInnerForward.out create mode 100644 src/tests/encore/forward/forwardNestedForward.enc create mode 100644 src/tests/encore/forward/forwardNestedForward.out delete mode 100644 src/tests/encore/forward/forwardPreexistingFuture.fail create mode 100644 src/tests/encore/forward/forwardPreexistingFuture.out create mode 100644 src/tests/encore/forward/forwardPreexistingFutureChain.enc create mode 100644 src/tests/encore/forward/forwardPreexistingFutureChain.out create mode 100644 src/tests/encore/forward/forwardPreexistingFutureFunctionCall.enc create mode 100644 src/tests/encore/forward/forwardPreexistingFutureFunctionCall.out diff --git a/src/back/CodeGen/CCodeNames.hs b/src/back/CodeGen/CCodeNames.hs index d942087e8..e75ae1353 100644 --- a/src/back/CodeGen/CCodeNames.hs +++ b/src/back/CodeGen/CCodeNames.hs @@ -213,7 +213,7 @@ methodImplNameStr clazz mname = forwardingMethodImplNameStr :: Ty.Type -> ID.Name -> String forwardingMethodImplNameStr clazz mname = - encoreName "forwarding_method" $ qualifyRefType clazz ++ "_" ++ show mname + encoreName "method" $ qualifyRefType clazz ++ "_" ++ show mname ++ "_async" callMethodFutureNameStr :: Ty.Type -> ID.Name -> String callMethodFutureNameStr clazz mname = @@ -449,6 +449,9 @@ futureGetActor = Nam "future_get_actor" futureChainActor :: CCode Name futureChainActor = Nam "future_chain_actor" +futureChainActorForward :: CCode Name +futureChainActorForward = Nam "future_chain_forward" + actorSuspend :: CCode Name actorSuspend = Nam "actor_suspend" diff --git a/src/back/CodeGen/Context.hs b/src/back/CodeGen/Context.hs index 03f3a16d5..e8aab5dbf 100644 --- a/src/back/CodeGen/Context.hs +++ b/src/back/CodeGen/Context.hs @@ -23,7 +23,7 @@ module CodeGen.Context ( setFunCtx, setClsCtx, getExecCtx, - withForwarding + isAsyncForward ) where import Identifiers @@ -74,8 +74,8 @@ newWithForwarding subs table = Context { ,withForward = True } -withForwarding :: Context -> Bool -withForwarding Context{withForward} = withForward +isAsyncForward :: Context -> Bool +isAsyncForward Context{withForward} = withForward genNamedSym :: String -> State Context String genNamedSym name = do diff --git a/src/back/CodeGen/Expr.hs b/src/back/CodeGen/Expr.hs index ae01f69f4..85977d59f 100644 --- a/src/back/CodeGen/Expr.hs +++ b/src/back/CodeGen/Expr.hs @@ -1015,18 +1015,10 @@ instance Translatable A.Expr (State Ctx.Context (CCode Lval, CCode Stat)) where ,A.name ,A.typeArguments ,A.args}} = do - withForwarding <- gets Ctx.withForwarding + isAsyncForward <- gets Ctx.isAsyncForward eCtx <- gets Ctx.getExecCtx - let dtraceExit = - case eCtx of - Ctx.FunctionContext fun -> - dtraceFunctionExit (A.functionName fun) - Ctx.MethodContext mdecl -> - dtraceMethodExit thisVar (A.methodName mdecl) - Ctx.ClosureContext clos -> - dtraceClosureExit - _ -> error "Expr.hs: No context to forward from" - if withForwarding + let dtraceExit = getDtraceExit eCtx + if isAsyncForward then do (ntarget, ttarget) <- translate target let targetType = A.getType target @@ -1049,8 +1041,7 @@ instance Translatable A.Expr (State Ctx.Context (CCode Lval, CCode Stat)) where dtraceExit, Return Skip]) - else if Ty.isFutureType $ A.getType expr - then do + else do (sendn, sendt) <- translate A.MessageSend{A.emeta ,A.target ,A.name @@ -1059,14 +1050,39 @@ instance Translatable A.Expr (State Ctx.Context (CCode Lval, CCode Stat)) where let resultType = translate (Ty.getResultType $ A.getType expr) theGet = fromEncoreArgT resultType (Call futureGetActor [encoreCtxVar, sendn]) return (unit, Seq [sendt, dtraceExit, Return theGet]) - else - error $ "Expr.hs: Cannot translate forward of ''" ++ show expr ++ "'" - translate A.Forward{A.forwardExpr = A.FutureChain{}} = - error "Expr.hs: Forwarding of chaining not implemented" - translate A.Forward{A.forwardExpr} = - error $ "Expr.hs: Target of forward is not method call or future chain: '" ++ - show forwardExpr ++ "'" + translate A.Forward{A.emeta, A.forwardExpr = fchain@A.FutureChain{A.future, A.chain}} = do + (nfuture,tfuture) <- translate future + (nchain, tchain) <- translate chain + eCtx <- gets $ Ctx.getExecCtx + isAsyncForward <- gets Ctx.isAsyncForward + let ty = getRuntimeType chain + dtraceExit = getDtraceExit eCtx + if isAsyncForward + then do + return (unit, Seq $ + [tfuture, + tchain, + (Statement $ + Call futureChainActorForward + [AsExpr encoreCtxVar, AsExpr nfuture, ty, AsExpr nchain, AsExpr futVar] + )] ++ + [dtraceExit, + Return Skip]) + else do + tmp <- Ctx.genSym + result <- Ctx.genSym + let nfchain = Var result + resultType = translate (Ty.getResultType $ A.getType fchain) + theGet = fromEncoreArgT resultType (Call futureGetActor [encoreCtxVar, nfchain]) + return $ (Var tmp, Seq $ + [tfuture, + tchain, + (Assign (Decl (C.future, Var result)) + (Call futureChainActor + [AsExpr encoreCtxVar, AsExpr nfuture, ty, AsExpr nchain] + )), + Assign (Decl (resultType, Var tmp)) theGet]) translate yield@(A.Yield{A.val}) = do (nval, tval) <- translate val @@ -1187,6 +1203,16 @@ instance Translatable A.Expr (State Ctx.Context (CCode Lval, CCode Stat)) where translate other = error $ "Expr.hs: can't translate: '" ++ show other ++ "'" +getDtraceExit eCtx = + case eCtx of + Ctx.FunctionContext fun -> + dtraceFunctionExit (A.functionName fun) + Ctx.MethodContext mdecl -> + dtraceMethodExit thisVar (A.methodName mdecl) + Ctx.ClosureContext clos -> + dtraceClosureExit + _ -> error "Expr.hs: No context to forward from" + closureCall :: CCode Lval -> A.Expr -> State Ctx.Context (CCode Lval, CCode Stat) closureCall clos fcall@A.FunctionCall{A.qname, A.args} = do diff --git a/src/opt/Optimizer/Optimizer.hs b/src/opt/Optimizer/Optimizer.hs index a0ce38d16..456e7300c 100644 --- a/src/opt/Optimizer/Optimizer.hs +++ b/src/opt/Optimizer/Optimizer.hs @@ -3,6 +3,7 @@ module Optimizer.Optimizer(optimizeProgram) where import Identifiers import AST.AST import AST.Util +import qualified AST.Meta as Meta import Types import Control.Applicative (liftA2) @@ -30,7 +31,7 @@ optimizeProgram p@(Program{classes, traits, functions}) = -- | The functions in this list will be performed in order during optimization optimizerPasses :: [Expr -> Expr] optimizerPasses = [constantFolding, sugarPrintedStrings, tupleMaybeIdComparison, - dropBorrowBlocks] + dropBorrowBlocks, forwardGeneral] -- Note that this is not intended as a serious optimization, but -- as an example to how an optimization could be made. As soon as @@ -128,3 +129,30 @@ dropBorrowBlocks = extend dropBorrowBlock ,decls = [([VarNoType name], target)] ,body} dropBorrowBlock e = e + +forwardGeneral = extend forwardGeneral' + where + forwardGeneral' e@(Forward{forwardExpr=MessageSend{}}) = e + + forwardGeneral' e@(Forward{forwardExpr=FutureChain{}}) = e + + forwardGeneral' e@(Forward{emeta, forwardExpr}) = + Forward{emeta=emeta', forwardExpr=newExpr} + where + emeta' = Meta.setType (Meta.getType emeta) (Meta.meta $ Meta.getPos emeta) + newExpr = FutureChain{emeta=fcmeta, future=forwardExpr, chain=idfun} + fcmeta = Meta.setType (getType $ forwardExpr) (Meta.meta (Meta.getPos emeta')) + idfun = Closure {emeta=mclosure + ,eparams=[pdecl] + ,mty=Just closureType + ,body=VarAccess {emeta=Meta.setType paramType mclosure + ,qname=qName "_id_fun_tmp"}} + closureType = arrowType [paramType] paramType + mclosure = Meta.metaClosure "" (Meta.setType closureType emeta) + paramType = getResultType . getType $ forwardExpr + pdecl = Param {pmeta=Meta.setType paramType (Meta.meta (Meta.getPos emeta)) + ,pmut =Val + ,pname=Name "_id_fun_tmp" + ,ptype=paramType} + + forwardGeneral' e = e diff --git a/src/runtime/future/future.c b/src/runtime/future/future.c index b726d9ce2..5a23bb381 100644 --- a/src/runtime/future/future.c +++ b/src/runtime/future/future.c @@ -101,6 +101,8 @@ static void future_block_actor(pony_ctx_t **ctx, future_t *fut); static void future_finalizer(future_t *fut); static inline void future_gc_send_value(pony_ctx_t *ctx, future_t *fut); static inline void future_gc_recv_value(pony_ctx_t *ctx, future_t *fut); +static void future_chain(pony_ctx_t **ctx, future_t *fut, pony_type_t *type, + closure_t *c, future_t *r); pony_type_t future_type = { .id = ID_FUTURE, @@ -303,6 +305,23 @@ future_t *future_chain_actor(pony_ctx_t **ctx, future_t *fut, pony_type_t *type, { ENC_DTRACE3(FUTURE_CHAINING, (uintptr_t) *ctx, (uintptr_t) fut, (uintptr_t) type); future_t *r = future_mk(ctx, type); + future_chain(ctx, fut, type, c, r); + return r; +} + +void future_chain_forward(pony_ctx_t **ctx, future_t *fut, pony_type_t *type, + closure_t *c, future_t *r) +{ + ENC_DTRACE3(FUTURE_CHAINING, (uintptr_t) *ctx, (uintptr_t) fut, (uintptr_t) type); + (void)type; + future_chain(ctx, fut, type, c, r); + return; +} + +static void future_chain(pony_ctx_t **ctx, future_t *fut, pony_type_t *type, + closure_t *c, future_t *r) +{ + (void)type; perr("future_chain_actor"); BLOCK; @@ -311,7 +330,7 @@ future_t *future_chain_actor(pony_ctx_t **ctx, future_t *fut, pony_type_t *type, value_t result = run_closure(ctx, c, fut->value); future_fulfil(ctx, r, result); UNBLOCK; - return r; + return; } pony_ctx_t* cctx = *ctx; @@ -329,11 +348,8 @@ future_t *future_chain_actor(pony_ctx_t **ctx, future_t *fut, pony_type_t *type, UNBLOCK; r->parent = fut; - - return r; } - // Similar to `future_chain_actor` except that it returns void, avoiding the // creation of a new future. This is used in the ParTs library and is an // optimisation over the `future_chain_actor`. diff --git a/src/runtime/future/future.h b/src/runtime/future/future.h index 73734ad50..505c0c360 100644 --- a/src/runtime/future/future.h +++ b/src/runtime/future/future.h @@ -54,6 +54,9 @@ encore_arg_t future_get_actor(pony_ctx_t **ctx, future_t *fut); future_t *future_chain_actor(pony_ctx_t **ctx, future_t *fut, pony_type_t *type, closure_t *c); +void future_chain_forward(pony_ctx_t **ctx, future_t *fut, pony_type_t *type, + closure_t *c, future_t *r); + /** Registers a callback and returns void * * diff --git a/src/tests/encore/forward/forwardChaining.enc b/src/tests/encore/forward/forwardChaining.enc index e1b966af9..5d0eb08e9 100644 --- a/src/tests/encore/forward/forwardChaining.enc +++ b/src/tests/encore/forward/forwardChaining.enc @@ -2,10 +2,13 @@ active class SnowyDay def snow() : int 42 end + def fall() : int + forward((new SnowyDay)!snow() ~~> fun (x: int) => x*10) + end end active class Main def main() : unit - forward((new SnowyDay)!snow() ~~> fun (x: int) => ()) + println("{}",get((new SnowyDay) ! fall())) end end diff --git a/src/tests/encore/forward/forwardChaining.fail b/src/tests/encore/forward/forwardChaining.fail deleted file mode 100644 index 77f1d280f..000000000 --- a/src/tests/encore/forward/forwardChaining.fail +++ /dev/null @@ -1 +0,0 @@ -Forward currently operates on method call diff --git a/src/tests/encore/forward/forwardChaining.out b/src/tests/encore/forward/forwardChaining.out new file mode 100644 index 000000000..816d01be5 --- /dev/null +++ b/src/tests/encore/forward/forwardChaining.out @@ -0,0 +1 @@ +420 diff --git a/src/tests/encore/forward/forwardCoverage.enc b/src/tests/encore/forward/forwardCoverage.enc new file mode 100644 index 000000000..dcd7bfbe7 --- /dev/null +++ b/src/tests/encore/forward/forwardCoverage.enc @@ -0,0 +1,34 @@ +fun id[t](x: t) : t + x +end + +active class Foo + + def multiChainWithExistingFuture(arg: Fut[int]) : int + val f = fun (x: int) => x + 1 + forward(arg ~~> f ~~> f ~~> f ~~> f ~~> f) + end + + def multiChainWithId(arg: Fut[int]) : int + val f = fun (x: int) => x + 1 + forward(id(arg ~~> f) ~~> f ~~> f ~~> f ~~> f) + end + + def multiChainWithMethodCall() : int + val f = fun (x: int) => x + 1 + forward(((new Foo) ! foo()) ~~> f ~~> f ~~> f ~~> f ~~> f) + end + + def foo() : int + 42 + end +end + +active class Main + def main() : unit + val foo = (new Foo) ! foo() + println("{}", get((new Foo) ! multiChainWithExistingFuture(foo))) + println("{}", get((new Foo) ! multiChainWithId(foo))) + println("{}", get((new Foo) ! multiChainWithMethodCall())) + end +end diff --git a/src/tests/encore/forward/forwardCoverage.out b/src/tests/encore/forward/forwardCoverage.out new file mode 100644 index 000000000..a445a53b6 --- /dev/null +++ b/src/tests/encore/forward/forwardCoverage.out @@ -0,0 +1,3 @@ +47 +47 +47 diff --git a/src/tests/encore/forward/forwardFieldAccess.enc b/src/tests/encore/forward/forwardFieldAccess.enc new file mode 100644 index 000000000..3dd21e8b6 --- /dev/null +++ b/src/tests/encore/forward/forwardFieldAccess.enc @@ -0,0 +1,26 @@ +active class Bar + def bar() : int + 42 + end +end + +active class Foo + var result : Fut[int] + + def init(arg : Fut[int]) : unit + this.result = arg + end + + def foo_arg() : int + forward(this.result) + end + +end + +active class Main + def main() : unit + val bar = (new Bar) ! bar() + val foo = new Foo(bar) + println("{}", get(foo ! foo_arg())) + end +end diff --git a/src/tests/encore/forward/forwardFieldAccess.out b/src/tests/encore/forward/forwardFieldAccess.out new file mode 100644 index 000000000..d81cc0710 --- /dev/null +++ b/src/tests/encore/forward/forwardFieldAccess.out @@ -0,0 +1 @@ +42 diff --git a/src/tests/encore/forward/forwardInnerForward.enc b/src/tests/encore/forward/forwardInnerForward.enc new file mode 100644 index 000000000..6485a139a --- /dev/null +++ b/src/tests/encore/forward/forwardInnerForward.enc @@ -0,0 +1,31 @@ +active class Base + def base() : int + 42 + end +end + +active class Bar + def bar() : int + 24 + end +end + +active class Foo + def foo(b : bool) : int + val arg1 = (new Bar) ! bar() + val arg2 = (new Base) ! base() + forward(if b then + forward(arg1) + arg1 -- required to make typecheck + else + arg2 + end) + end +end + +active class Main + def main() : unit + println("{}", get((new Foo) ! foo(true))) + println("{}", get((new Foo) ! foo(false))) + end +end diff --git a/src/tests/encore/forward/forwardInnerForward.out b/src/tests/encore/forward/forwardInnerForward.out new file mode 100644 index 000000000..a1b6a6a9a --- /dev/null +++ b/src/tests/encore/forward/forwardInnerForward.out @@ -0,0 +1,2 @@ +24 +42 diff --git a/src/tests/encore/forward/forwardNestedForward.enc b/src/tests/encore/forward/forwardNestedForward.enc new file mode 100644 index 000000000..ad221237c --- /dev/null +++ b/src/tests/encore/forward/forwardNestedForward.enc @@ -0,0 +1,29 @@ +active class Base + def base() : int + 42 + end +end + +active class Ground + def ground() : int + forward((new Base) ! base()) + end +end + +active class Bar + def bar() : int + forward((new Ground) ! ground()) + end +end + +active class Foo + def foo() : int + forward((new Bar) ! bar()) + end +end + +active class Main + def main() : unit + println("{}", get((new Foo) ! foo())) + end +end diff --git a/src/tests/encore/forward/forwardNestedForward.out b/src/tests/encore/forward/forwardNestedForward.out new file mode 100644 index 000000000..d81cc0710 --- /dev/null +++ b/src/tests/encore/forward/forwardNestedForward.out @@ -0,0 +1 @@ +42 diff --git a/src/tests/encore/forward/forwardPreexistingFuture.enc b/src/tests/encore/forward/forwardPreexistingFuture.enc index 8978faf6c..f259d438b 100644 --- a/src/tests/encore/forward/forwardPreexistingFuture.enc +++ b/src/tests/encore/forward/forwardPreexistingFuture.enc @@ -2,10 +2,14 @@ active class Foo def foo_arg(arg: Fut[int]) : int forward(arg) end + def foo() : int + 42 + end end active class Main def main() : unit - () + val foo = (new Foo) ! foo() + println("{}", get((new Foo)!foo_arg(foo))) end end diff --git a/src/tests/encore/forward/forwardPreexistingFuture.fail b/src/tests/encore/forward/forwardPreexistingFuture.fail deleted file mode 100644 index 77f1d280f..000000000 --- a/src/tests/encore/forward/forwardPreexistingFuture.fail +++ /dev/null @@ -1 +0,0 @@ -Forward currently operates on method call diff --git a/src/tests/encore/forward/forwardPreexistingFuture.out b/src/tests/encore/forward/forwardPreexistingFuture.out new file mode 100644 index 000000000..d81cc0710 --- /dev/null +++ b/src/tests/encore/forward/forwardPreexistingFuture.out @@ -0,0 +1 @@ +42 diff --git a/src/tests/encore/forward/forwardPreexistingFutureChain.enc b/src/tests/encore/forward/forwardPreexistingFutureChain.enc new file mode 100644 index 000000000..cc71f6c1e --- /dev/null +++ b/src/tests/encore/forward/forwardPreexistingFutureChain.enc @@ -0,0 +1,19 @@ +-- TEST FORWARD, PREEXISTING FUTURE CHAINING +active class Foo + def two(x : int) : int + x + end +end + +active class Base + def one(arg : Fut[int]) : int + forward(arg ~~> fun (x:int) => x) + end +end + +active class Main + def main() : unit + val arg = (new Foo)!two(42) + println("{}",get((new Base)!one(arg))) + end +end diff --git a/src/tests/encore/forward/forwardPreexistingFutureChain.out b/src/tests/encore/forward/forwardPreexistingFutureChain.out new file mode 100644 index 000000000..d81cc0710 --- /dev/null +++ b/src/tests/encore/forward/forwardPreexistingFutureChain.out @@ -0,0 +1 @@ +42 diff --git a/src/tests/encore/forward/forwardPreexistingFutureFunctionCall.enc b/src/tests/encore/forward/forwardPreexistingFutureFunctionCall.enc new file mode 100644 index 000000000..cf90bf3e9 --- /dev/null +++ b/src/tests/encore/forward/forwardPreexistingFutureFunctionCall.enc @@ -0,0 +1,19 @@ +fun id[t](x: t) : t + x +end + +active class Foo + def foo_arg(arg: Fut[int]) : int + forward(id(arg)) + end + def foo() : int + 42 + end +end + +active class Main + def main() : unit + val foo = (new Foo) ! foo() + println("{}", get((new Foo)!foo_arg(foo))) + end +end diff --git a/src/tests/encore/forward/forwardPreexistingFutureFunctionCall.out b/src/tests/encore/forward/forwardPreexistingFutureFunctionCall.out new file mode 100644 index 000000000..d81cc0710 --- /dev/null +++ b/src/tests/encore/forward/forwardPreexistingFutureFunctionCall.out @@ -0,0 +1 @@ +42 diff --git a/src/types/Typechecker/TypeError.hs b/src/types/Typechecker/TypeError.hs index 36f230163..a691bcba7 100644 --- a/src/types/Typechecker/TypeError.hs +++ b/src/types/Typechecker/TypeError.hs @@ -115,7 +115,6 @@ validUseOfBreak :: Backtrace -> Bool validUseOfBreak [] = False validUseOfBreak ((_, BTExpr l@For{}):_) = True validUseOfBreak ((_, BTExpr l@While{}):_) = True -validUseOfBreak ((_, BTExpr l@DoWhile{}):_) = True validUseOfBreak ((_, BTExpr l@Repeat{}):_) = True validUseOfBreak ((_, BTExpr c@Closure{}):_) = False validUseOfBreak (_:bt) = validUseOfBreak bt @@ -291,7 +290,6 @@ data Error = | ImpureMatchMethodError Expr | IdComparisonNotSupportedError Type | IdComparisonTypeMismatchError Type Type - | ForwardArgumentError | ForwardInPassiveContext Type | ForwardInFunction | ForwardTypeError Type Type @@ -720,7 +718,6 @@ instance Show Error where printf ("Returned type %s of forward should match with " ++ "the result type of the containing method %s") (show retType) (show ty) - show (ForwardArgumentError) = "Forward currently operates on method call" show (ForwardInPassiveContext cname) = printf "Forward can not be used in passive class '%s'" (show cname) @@ -967,4 +964,4 @@ instance Show Warning where "This will be fixed in a later version of Encore." show CapabilitySplitWarning = "Unpacking linear capabilities is not fully supported and may be unsafe. " ++ - "This will be fixed in a later version of Encore." \ No newline at end of file + "This will be fixed in a later version of Encore." diff --git a/src/types/Typechecker/Typechecker.hs b/src/types/Typechecker/Typechecker.hs index a30b4c64a..45df82175 100644 --- a/src/types/Typechecker/Typechecker.hs +++ b/src/types/Typechecker/Typechecker.hs @@ -1234,8 +1234,6 @@ instance Checkable Expr where doTypecheck forward@(Forward {forwardExpr}) = do eExpr <- typecheck forwardExpr let ty = AST.getType eExpr - unless (isMessageSend forwardExpr) $ - pushError eExpr $ ForwardArgumentError unless (isFutureType ty) $ pushError eExpr $ ExpectingOtherTypeError "a future" ty From 115de29a87d31d13d01c8bfc8bc171c522aa4c41 Mon Sep 17 00:00:00 2001 From: supercooldave Date: Thu, 4 May 2017 21:27:37 +0200 Subject: [PATCH 08/18] Moved tests from modules directory to test directory (#800) --- .../Boxed => src/tests/encore/stdlib/Data}/BoxedTest.enc | 0 src/tests/encore/stdlib/Data/BoxedTest.out | 9 +++++++++ .../tests/encore/stdlib}/Set/OrderedSetTest.enc | 0 src/tests/encore/stdlib/Set/OrderedSetTest.out | 1 + 4 files changed, 10 insertions(+) rename {modules/standard/Boxed => src/tests/encore/stdlib/Data}/BoxedTest.enc (100%) create mode 100644 src/tests/encore/stdlib/Data/BoxedTest.out rename {modules/standard => src/tests/encore/stdlib}/Set/OrderedSetTest.enc (100%) create mode 100644 src/tests/encore/stdlib/Set/OrderedSetTest.out diff --git a/modules/standard/Boxed/BoxedTest.enc b/src/tests/encore/stdlib/Data/BoxedTest.enc similarity index 100% rename from modules/standard/Boxed/BoxedTest.enc rename to src/tests/encore/stdlib/Data/BoxedTest.enc diff --git a/src/tests/encore/stdlib/Data/BoxedTest.out b/src/tests/encore/stdlib/Data/BoxedTest.out new file mode 100644 index 000000000..d28e6cdc5 --- /dev/null +++ b/src/tests/encore/stdlib/Data/BoxedTest.out @@ -0,0 +1,9 @@ +12 +-200 +a +1.7977e+308 +1.234 +-1.7977e+308 +true +false +() diff --git a/modules/standard/Set/OrderedSetTest.enc b/src/tests/encore/stdlib/Set/OrderedSetTest.enc similarity index 100% rename from modules/standard/Set/OrderedSetTest.enc rename to src/tests/encore/stdlib/Set/OrderedSetTest.enc diff --git a/src/tests/encore/stdlib/Set/OrderedSetTest.out b/src/tests/encore/stdlib/Set/OrderedSetTest.out new file mode 100644 index 000000000..19f86f493 --- /dev/null +++ b/src/tests/encore/stdlib/Set/OrderedSetTest.out @@ -0,0 +1 @@ +done From c2e712a76c844c691e89249f3f096b0f351f7a50 Mon Sep 17 00:00:00 2001 From: Elias Castegren Date: Fri, 12 May 2017 16:33:08 +0200 Subject: [PATCH 09/18] Remove C-warning when using non unit-typed loops (#803) This commit gets rid of a C-warning when the body of a loop does not have the type `unit`. No test has been added, as warning output cannot be tested. Fixes #759. --- src/back/CodeGen/Expr.hs | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/src/back/CodeGen/Expr.hs b/src/back/CodeGen/Expr.hs index 85977d59f..5fb0aec0d 100644 --- a/src/back/CodeGen/Expr.hs +++ b/src/back/CodeGen/Expr.hs @@ -663,26 +663,17 @@ instance Translatable A.Expr (State Ctx.Context (CCode Lval, CCode Stat)) where result <- Ctx.genNamedSym (fromJust sym) return (Var result, Assign (Decl (translate retTy, Var result))) - translate w@(A.DoWhile {A.cond, A.body}) = - do (ncond,tcond) <- translate cond - (nbody,tbody) <- translate body - tmp <- Ctx.genNamedSym "while"; - let exportBody = Seq $ tbody : [Assign (Var tmp) nbody] - return (Var tmp, - Seq [Statement $ Decl (translate (A.getType w), Var tmp), - DoWhile (StatAsExpr ncond tcond) (Statement exportBody)]) - - translate w@(A.While {A.cond, A.body}) = - do (ncond,tcond) <- translate cond - (nbody,tbody) <- translate body - tmp <- Ctx.genNamedSym "while"; - let exportBody = Seq $ tbody : [Assign (Var tmp) nbody] - return (Var tmp, - Seq [Statement $ Decl (translate (A.getType w), Var tmp), - While (StatAsExpr ncond tcond) (Statement exportBody)]) + translate w@(A.DoWhile {A.cond, A.body}) = do + (ncond,tcond) <- translate cond + (_,tbody) <- translate body + return (unit, DoWhile (StatAsExpr ncond tcond) (Statement tbody)) + + translate w@(A.While {A.cond, A.body}) = do + (ncond,tcond) <- translate cond + (_,tbody) <- translate body + return (unit, While (StatAsExpr ncond tcond) (Statement tbody)) translate for@(A.For {A.name, A.step, A.src, A.body}) = do - tmpVar <- Var <$> Ctx.genNamedSym "for"; indexVar <- Var <$> Ctx.genNamedSym "index" eltVar <- Var <$> Ctx.genNamedSym (show name) startVar <- Var <$> Ctx.genNamedSym "start" @@ -736,12 +727,10 @@ instance Translatable A.Expr (State Ctx.Context (CCode Lval, CCode Stat)) where then AsExpr indexVar else AsExpr $ fromEncoreArgT eltType (Call arrayGet [srcN, indexVar])) inc = Assign indexVar (BinOp (translate ID.PLUS) indexVar stepVar) - theBody = Seq [eltDecl, Statement bodyT, Assign tmpVar bodyN, inc] + theBody = Seq [eltDecl, Statement bodyT, inc] theLoop = While cond theBody - tmpDecl = Statement $ Decl (translate (A.getType for), tmpVar) - return (tmpVar, Seq [tmpDecl - ,srcT + return (unit, Seq [srcT ,srcStartT ,srcStopT ,srcStepT From 9caa5e483c17748f864f45be8758c8f294255c18 Mon Sep 17 00:00:00 2001 From: Elias Castegren Date: Fri, 12 May 2017 17:01:14 +0200 Subject: [PATCH 10/18] Print file and line number for uncaught matches (#804) This commit adds to the error message the position of a match expression when no case matches. A test has been added. Fixes #733. --- src/back/CodeGen/Expr.hs | 10 +++++----- src/tests/encore/match/missing.enc | 9 +++++++++ src/tests/encore/match/missing.err | 1 + 3 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 src/tests/encore/match/missing.enc create mode 100644 src/tests/encore/match/missing.err diff --git a/src/back/CodeGen/Expr.hs b/src/back/CodeGen/Expr.hs index 5fb0aec0d..0fbd0e3fc 100644 --- a/src/back/CodeGen/Expr.hs +++ b/src/back/CodeGen/Expr.hs @@ -763,7 +763,7 @@ instance Translatable A.Expr (State Ctx.Context (CCode Lval, CCode Stat)) where (narg, targ) <- translate arg let argty = A.getType arg mType = translate (A.getType m) - tIfChain <- ifChain clauses narg argty retTmp mType + tIfChain <- ifChain clauses narg argty retTmp mType (A.getPos m) let lRetDecl = Decl (mType, Var retTmp) eZeroInit = Cast mType (Int 0) tRetDecl = Assign lRetDecl eZeroInit @@ -930,18 +930,18 @@ instance Translatable A.Expr (State Ctx.Context (CCode Lval, CCode Stat)) where tAssign = Assign (Var handlerReturnVar) eCast return tAssign - ifChain [] _ _ _ _ = do + ifChain [] _ _ _ _ pos = do let errorCode = Int 1 exitCall = Statement $ Call (Nam "exit") [errorCode] - errorMsg = String "*** Runtime error: No matching clause was found ***\n" + errorMsg = String $ "*** Runtime error: No matching clause was found at " ++ show pos ++ " ***\n" errorPrint = Statement $ Call (Nam "fprintf") [AsExpr C.stderr, errorMsg] return $ Seq [errorPrint, exitCall] - ifChain (clause:rest) narg argty retTmp retTy = do + ifChain (clause:rest) narg argty retTmp retTy pos = do let freeVars = Util.foldrExp (\e a -> getExprVars e ++ a) [] (A.mcpattern clause) assocs <- mapM createAssoc freeVars thenExpr <- translateHandler clause retTmp assocs retTy - elseExpr <- ifChain rest narg argty retTmp retTy + elseExpr <- ifChain rest narg argty retTmp retTy pos eCond <- translateIfCond clause narg argty assocs let tIf = Statement $ If eCond thenExpr elseExpr tDecls = Seq $ map (fwdDecl assocs) freeVars diff --git a/src/tests/encore/match/missing.enc b/src/tests/encore/match/missing.enc new file mode 100644 index 000000000..090c1b71e --- /dev/null +++ b/src/tests/encore/match/missing.enc @@ -0,0 +1,9 @@ +active class Main + def main(args : [String]) : unit + match 1 with + case 2 => + println("This should not happen!") + end + end + end +end \ No newline at end of file diff --git a/src/tests/encore/match/missing.err b/src/tests/encore/match/missing.err new file mode 100644 index 000000000..1a661c478 --- /dev/null +++ b/src/tests/encore/match/missing.err @@ -0,0 +1 @@ +*** Runtime error: No matching clause was found at "missing.enc" (line 3, column 5) *** From c20ff98fda2f490eeb2207c2be5727487569dffe Mon Sep 17 00:00:00 2001 From: helanhalvan Date: Tue, 30 May 2017 15:01:52 +0200 Subject: [PATCH 11/18] Adding Pedestrian simulation stress test (#794) * Adding Pedestrian simulation stress test. For configuration options, see src/tests/stress/pedsim/README.md * Removed some unused methods, comments, general cleanup * more cleanup * used private method keyword to make a method private * removed binary file * removed big problem instances * removed big problem instances * Fixed dumb of by one in setup * undid unintential change to Makefile * Lifted number of time steps to become a parameter for the simulation * Lots of small changes * Changed an error message to make dave less sad * removed binary file --- src/tests/IGNORED_FILES.grep | 8 +- src/tests/stress/pedsim/16000_scenario.xml | 16 + src/tests/stress/pedsim/2000_scenario.xml | 16 + src/tests/stress/pedsim/4000_scenario.xml | 16 + src/tests/stress/pedsim/400_scenario.xml | 16 + .../stress/pedsim/Ped_util/Agent_passive.enc | 93 ++++ .../stress/pedsim/Ped_util/Global_funs.enc | 213 ++++++++ src/tests/stress/pedsim/Ped_util/IO.enc | 78 +++ .../stress/pedsim/Ped_util/Quad_tree.enc | 153 ++++++ src/tests/stress/pedsim/Ped_util/Regions.enc | 456 ++++++++++++++++++ src/tests/stress/pedsim/Ped_util/XML.enc | 230 +++++++++ src/tests/stress/pedsim/README.md | 11 + src/tests/stress/pedsim/parallel_small.enc | 16 + src/tests/stress/pedsim/parallel_small.out | 1 + src/tests/stress/pedsim/serial_big.enc | 16 + src/tests/stress/pedsim/serial_big.out | 1 + 16 files changed, 1339 insertions(+), 1 deletion(-) create mode 100644 src/tests/stress/pedsim/16000_scenario.xml create mode 100644 src/tests/stress/pedsim/2000_scenario.xml create mode 100644 src/tests/stress/pedsim/4000_scenario.xml create mode 100644 src/tests/stress/pedsim/400_scenario.xml create mode 100644 src/tests/stress/pedsim/Ped_util/Agent_passive.enc create mode 100644 src/tests/stress/pedsim/Ped_util/Global_funs.enc create mode 100644 src/tests/stress/pedsim/Ped_util/IO.enc create mode 100644 src/tests/stress/pedsim/Ped_util/Quad_tree.enc create mode 100644 src/tests/stress/pedsim/Ped_util/Regions.enc create mode 100644 src/tests/stress/pedsim/Ped_util/XML.enc create mode 100644 src/tests/stress/pedsim/README.md create mode 100644 src/tests/stress/pedsim/parallel_small.enc create mode 100644 src/tests/stress/pedsim/parallel_small.out create mode 100644 src/tests/stress/pedsim/serial_big.enc create mode 100644 src/tests/stress/pedsim/serial_big.out diff --git a/src/tests/IGNORED_FILES.grep b/src/tests/IGNORED_FILES.grep index f429991c2..8b86135ce 100644 --- a/src/tests/IGNORED_FILES.grep +++ b/src/tests/IGNORED_FILES.grep @@ -1,6 +1,13 @@ # This file support line comments. # Note that the # must appear first on the line +#Pedsim util modules should not be considered tests +stress/pedsim/Ped_util/Agent_passive +stress/pedsim/Ped_util/Global_funs +stress/pedsim/Ped_util/IO +stress/pedsim/Ped_util/Quad_tree +stress/pedsim/Ped_util/Regions +stress/pedsim/Ped_util/XML # # Modules used by 'modules' tests # Should not be considered as tests @@ -52,4 +59,3 @@ encore/stream/StreamIO # Should not be considered as a test # stress/savina/7.Chameneos/List.enc - diff --git a/src/tests/stress/pedsim/16000_scenario.xml b/src/tests/stress/pedsim/16000_scenario.xml new file mode 100644 index 000000000..347a629a2 --- /dev/null +++ b/src/tests/stress/pedsim/16000_scenario.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/tests/stress/pedsim/2000_scenario.xml b/src/tests/stress/pedsim/2000_scenario.xml new file mode 100644 index 000000000..58781a11f --- /dev/null +++ b/src/tests/stress/pedsim/2000_scenario.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/tests/stress/pedsim/4000_scenario.xml b/src/tests/stress/pedsim/4000_scenario.xml new file mode 100644 index 000000000..6f140be57 --- /dev/null +++ b/src/tests/stress/pedsim/4000_scenario.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/tests/stress/pedsim/400_scenario.xml b/src/tests/stress/pedsim/400_scenario.xml new file mode 100644 index 000000000..efdd7a366 --- /dev/null +++ b/src/tests/stress/pedsim/400_scenario.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/tests/stress/pedsim/Ped_util/Agent_passive.enc b/src/tests/stress/pedsim/Ped_util/Agent_passive.enc new file mode 100644 index 000000000..37f713001 --- /dev/null +++ b/src/tests/stress/pedsim/Ped_util/Agent_passive.enc @@ -0,0 +1,93 @@ +module Agent_passive +import Global_funs +{- +Representation of one Agent in the simulation +-} +unsafe class Agent + var hash_code : uint + var x : int + var y : int + var targets_x : [int] + var targets_y : [int] + var targets_size : [int] + var i : int + var ttl : int + def init(in_pos : (int, int), list : [(int, int)], targets_size : [int], in_id : int, ttl : int) : unit + match in_pos with + case (x, y) => + this.x = x + this.y = y + end + end + this.i = 0 + this.targets_x = new [int](|targets_size|) + this.targets_y = new [int](|targets_size|) + this.targets_size = targets_size + for index <- [0..|list| - 1] do + match list(index) with + case (x, y) => + (this.targets_x)(index) = x + (this.targets_y)(index) = y + end + end + end + this.hash_code = in_id + this.ttl = ttl + () + end +--requires ret to be a size 6 [int] +--fills ret with desired positions in the format +--[this.x,this.y,x2,y2,x3,y3] + def next(ret : [int]) : unit + var x2 = (this.targets_x)(this.i) + var y2 = (this.targets_y)(this.i) + var xdiff = this.x - x2 + var ydiff = this.y - y2 + var len_square = xdiff * xdiff + ydiff * ydiff + var invlen = inv_sqrt(len_square) + --if inside the target waypoint, move towards the next waypoint + if len_square < (this.targets_size(this.i) * this.targets_size(this.i)) then + this.i = this.i + 1 + end + -- if after the last waypoint, use the firs waypoint + if |this.targets_size| == this.i then + this.i = 0 + end + x2 = (this.targets_x)(this.i) + y2 = (this.targets_y)(this.i) + xdiff = this.x - x2 + ydiff = this.y - y2 + len_square = xdiff * xdiff + ydiff * ydiff + invlen = inv_sqrt(len_square) + let + xoff = xdiff * invlen + yoff = ydiff * invlen + desired_x = this.x + round(xoff * -(1)) + desired_y = this.y + round(yoff * -(1)) + in + val dx = desired_x - this.x + val dy = desired_y - this.y + ret(0) = desired_x + ret(1) = desired_y + if dx == 0 || dy == 0 then + ret(2) = desired_x + dy + ret(3) = desired_y + dx + ret(4) = desired_x - dy + ret(5) = desired_y - dx + else + ret(2) = desired_x + ret(3) = this.y + ret(4) = this.x + ret(5) = desired_y + end + end + () + end + def move_int(x : int, y : int) : unit + this.x = x + this.y = y + end + def pos() : (int, int) + (this.x, this.y) + end +end diff --git a/src/tests/stress/pedsim/Ped_util/Global_funs.enc b/src/tests/stress/pedsim/Ped_util/Global_funs.enc new file mode 100644 index 000000000..1dd4c8108 --- /dev/null +++ b/src/tests/stress/pedsim/Ped_util/Global_funs.enc @@ -0,0 +1,213 @@ +module Global_funs +import Agent_passive +import XML +fun inv_sqrt(input : int) : real + var ret = 0.0 + EMBED (unit) + { + float x = #{input}; + float xhalf = 0.5f * x; + int i = *(int*)&x; + i = 0x5f3759df - (i >> 1); + x = *(float*)&i; + #{ret}= x*(1.5f - xhalf*x*x); + } + END + ret +end +fun find_extreme(agents : [Agent]) : (int, int, int, int) + var extreme = (agents(0).x,agents(0).y,agents(0).x,agents(0).y) + var i = 0 + for a <- agents do + i = i + 1 + extreme = extreme_check(a.pos(), extreme) + for index <- [0..|a.targets_x| - 1] do + extreme = extreme_check(((a.targets_x)(index), (a.targets_y)(index)), extreme) + end + end + extreme +end +fun extreme_check(a : (int, int), b : (int, int, int, int)) : (int, int, int, int) + match (a, b) with + case ((x, y), (xmax, ymax, xmin, ymin)) => + (max(x, xmax), max(y, ymax), min(x, xmin), min(y, ymin)) + end + end +end + +fun copy_ar(arr : [int]) : [int] + var a2 = new [int](|arr|) + var i = 0 + for a <- arr do + a2(i) = a + i = i + 1 + end + a2 +end +fun copy_tr(arr : [(int, int)]) : [(int, int)] + var a2 = new [(int, int)](|arr|) + var i = 0 + for a <- arr do + a2(i) = a + i = i + 1 + end + a2 +end +fun flatten(listlist : [[(int, int)]]) : [(int, int)] + var len = 0 + for a <- listlist do + len = len + |a| + end + var list = new [(int, int)](len) + var i = 0 + for a <- listlist do + for b <- a do + list(i) = b + i = i + 1 + end + end + list +end +fun max(a : int, b : int) : int + if a > b then + a + else + b + end +end +fun min(a : int, b : int) : int + if a < b then + a + else + b + end +end +fun yolo_int(i : Maybe[int]) : int + match i with + case Just(nr) => + nr + end + case _ => + abort("or0\nparsing error") + 0 + end + + end +end +fun yolo_string(i : Maybe[String]) : String + match i with + case Just(nr) => + nr + end + case _ => + abort("orEmpty\nparsing error") + "" + end + end +end +fun sqrt(nr : real) : real + EMBED (unit) + { #{nr}=sqrt(#{nr}); } + END + nr +end +fun abs(a : int) : int + if a > 0 then + a + else + a * -(1) + end +end + +fun round(x : real) : int + val i = 0 + EMBED (unit) + { #{i}=round(#{x}); } + END + i +end + +fun distance_int(x1 : int, y1 : int, x2 : int, y2 : int) : real + sqrt(x1 - x2 * x1 - x2 + y1 - y2 * y1 - y2) +end + +fun parse_file(fname : String) : [Agent] + var sen = new XML_lib() + var file = new XML_node() + do + match sen.file_to_xml(fname) with + case Just(xml) => + file = xml + end + case Nothing => + abort("XML parsing\n") + end + + end + var xml_way = file.children_named("waypoint") + var waypoints = new [(int, int)](|xml_way|) + var waypoints_distance = new [int](|xml_way|) + var i = 0 + do + for a <- xml_way do + waypoints(i) = match (a.attribute_value("x").to_int(), a.attribute_value("y").to_int()) with + case (Just(x), Just(y)) => + (x, y) + end + case _ => + print("BADINT!\n") + abort("parsing error") + (0,0) + end + + end + waypoints_distance(i) = yolo_int(a.attribute_value("r").to_int()) + i = i + 1 + end + var nr_agents = 0 + for a <- file.children_named("agent") do + nr_agents = nr_agents + yolo_int(a.attribute_value("n").to_int()) + end + var agents = new [Agent](nr_agents) + var i = 0 + do + for a <- file.children_named("agent") do + var max = yolo_int(a.attribute_value("n").to_int()) + var x = yolo_int(a.attribute_value("xs").to_int()) + var y = yolo_int(a.attribute_value("ys").to_int()) + var dx_max = yolo_int(a.attribute_value("dx").to_int()) / 2 + var dy_max = yolo_int(a.attribute_value("dy").to_int()) / 2 + var agent_waypoints = new [(int, int)](|a.children_named("addway")|) + var dx = x - dx_max + var dy = y - dy_max + var j = 0 + do + for b <- a.children_named("addway") do + agent_waypoints(j) = waypoints(yolo_int(yolo_string(b.attribute_value("id").substring(1, 2)).to_int()) - 1) + unless |agent_waypoints| > 1 then + print("THIS SHOULD NEVER HAPPEN |new_agent.waypoint|={}\n", |agent_waypoints|) + abort("agent_waypoint size error") + end + j = j + 1 + end + for unused <- [0..max-1] do + if dx > x + dx_max then + abort("out of space") + else + if dy > y + dy_max then + dy = y - dy_max + dx = dx + 1 + else + dy = dy + 1 + end + end + agents(i) = new Agent((dx, dy), copy_tr(agent_waypoints), copy_ar(waypoints_distance), i, 10000) + i = i + 1 + end + end + end + agents --consume + end + end + end +end diff --git a/src/tests/stress/pedsim/Ped_util/IO.enc b/src/tests/stress/pedsim/Ped_util/IO.enc new file mode 100644 index 000000000..f98ea9ec7 --- /dev/null +++ b/src/tests/stress/pedsim/Ped_util/IO.enc @@ -0,0 +1,78 @@ +module IO +{- +WARRNING this is a minimal untested file IO "library" +This should be replaced with standard library functionallity when that is available +-} +local class File + var file : EMBED FILE* END + var fname : String + var mode : String + def init(fname : String, mode : String) : unit + this.fname = fname + this.mode = mode + end + def open(fin : String, mode : String) : unit + this.mode = if mode.equals("") then + "w+r+a" + else + mode + end + this.fname = fin + var fin = fin.data + var mChar = this.mode.data + this.file = EMBED (EMBED FILE* END) + FILE *file = fopen(#{fin}, #{mChar}); + if (!file) { + printf("Cannot open file, exiting.\n"); + exit(1); + }; + file; + + END + end + def close() : unit + var f = this.file + this.file = EMBED (EMBED FILE* END) + if (!#{f}) { + printf("Cannot close file, exiting.\n"); + exit(1); + }; + fclose(#{f}); + (FILE*)NULL; + + END + end + def write(content : String) : unit + this.writeChar(content.data) + end + def writeChar(content : EMBED char* END) : unit + var file = this.file + EMBED (unit) + FILE *fout = #{file}; + if (!fout) { + printf("Cannot open file, exiting.\n"); + exit(1); + } + fprintf(fout, #{content}); + + END + end + def readline() : String + new String(this.readlineChar()) + end + def readlineChar() : EMBED char* END + var f = this.file + EMBED (EMBED char* END) + char* line = encore_alloc(*_ctx,255); + fgets(line, 255, #{f}); + line; + + END + end + def eof() : bool + var f = this.file + EMBED (bool) + feof(#{f}); + END + end +end diff --git a/src/tests/stress/pedsim/Ped_util/Quad_tree.enc b/src/tests/stress/pedsim/Ped_util/Quad_tree.enc new file mode 100644 index 000000000..c6ca5484b --- /dev/null +++ b/src/tests/stress/pedsim/Ped_util/Quad_tree.enc @@ -0,0 +1,153 @@ +module Quad_tree +import Global_funs +local class Quad + var agent : [int] + var top_right : Maybe[Quad] + var top_left : Maybe[Quad] + var bottom_right : Maybe[Quad] + var bottom_left : Maybe[Quad] + var max_x : int + var max_y : int + var min_x : int + var min_y : int + var size : int + def init(max_x : int, max_y : int, min_x : int, min_y : int) : unit + this.max_x = max_x + this.max_y = max_y + this.min_x = min_x + this.min_y = min_y + this.top_right=Nothing + this.top_left=Nothing + this.bottom_right=Nothing + this.bottom_left=Nothing + this.size = 0 + this.agent = new [int](0) + end + def add(x : int, y : int) : unit + match this.top_right with + case Nothing => + if |this.agent|==0 then + this.agent = new [int](2) + this.agent(0) = x + this.agent(1) = y + this.size = 1 + else + val dx = (this.max_x - this.min_x) / 2 + val dy = (this.max_y - this.min_y) / 2 + this.top_right = Just(new Quad(this.max_x, this.max_y, this.min_x + dx + 1, this.min_y + dy + 1)) + this.top_left = Just(new Quad(this.min_x + dx, this.max_y, this.min_x, this.min_y + dy + 1)) + this.bottom_right = Just(new Quad(this.max_x, this.min_y + dy, this.min_x + dx + 1, this.min_y)) + this.bottom_left = Just(new Quad(this.min_x + dx, this.min_y + dy, this.min_x, this.min_y)) + this.size = 2 + this.recur(this.agent(0), this.agent(1)).add(this.agent(0), this.agent(1)) + this.recur(x, y).add(x, y) + this.agent = new [int](0) + end + end + case unused => + this.size = this.size + 1 + this.recur(x, y).add(x, y) + end + end + end + def remove(x : int, y : int) : bool + match this.top_right with + case Nothing => + if this.same(x, y) then + this.agent = new[int](0) + this.size = 0 + true + else + false + end + end + case Just(unused) => + val hit = this.recur(x, y).remove(x, y) + if hit then + this.size = this.size - 1 + if this.size == 0 then + this.top_right = Nothing + this.bottom_right = Nothing + this.top_left = Nothing + this.bottom_left = Nothing + end + end + hit + end + end + end + def isin(x : int, y : int) : bool + match this.top_right with + case Nothing => this.same(x, y) + case Just(unused) => this.recur(x, y).isin(x, y) + end + end + def same(x : int, y : int) : bool + if |this.agent| == 2 && this.agent(0) == x && this.agent(1) == y then + true + else + false + end + end + --traverse down the tree, only call if not leaf + def recur(x : int, y : int) : Quad + val top = y > (((this.max_y - this.min_y) / 2) + this.min_y) + val right = x > (((this.max_x - this.min_x) / 2) + this.min_x) + if top then + if right then + match (this.top_right) with + case Just(qq) => qq + end + else + match (this.top_left) with + case Just(qq) => qq + end + end + else + if right then + match (this.bottom_right) with + case Just(qq) => qq + end + else + match (this.bottom_left) with + case Just(qq) => qq + end + end + end + end +end +local class Quad_tree + var tree : Quad + var xmax : int + var ymax : int + var xmin : int + var ymin : int + def init(in_max : (int, int), in_min : (int, int)) : unit + match (in_max, in_min) with + case ((xmax, ymax), (xmin, ymin)) => + this.tree = new Quad(xmax, ymax, xmin, ymin) + this.xmax = xmax + this.ymax = ymax + this.xmin = xmin + this.ymin = ymin + end + end + end + def get_val(x : int, y : int) : bool + this.tree.isin(x, y) + end + def set(x : int, y : int) : unit + if x > this.xmax || y > this.ymax || y < this.ymin || x < this.xmin then + abort("TRYING TO STORE VALUE OUTSIDE OF THIS TREE\n") + else + this.tree.add(x, y) + end + () + end + def remove(x : int, y : int) : bool + this.tree.remove(x, y) + end + def size() : int + this.tree.size + end +end diff --git a/src/tests/stress/pedsim/Ped_util/Regions.enc b/src/tests/stress/pedsim/Ped_util/Regions.enc new file mode 100644 index 000000000..c58befae9 --- /dev/null +++ b/src/tests/stress/pedsim/Ped_util/Regions.enc @@ -0,0 +1,456 @@ +module Regions +import Agent_passive +import Global_funs +import Quad_tree + +fun regions(var agents : [Agent], boxes : uint, steps : uint) : unit + var box = new Tiling_box(agents, boxes) + box!move(steps) +end +fun link(a : Box, b : Box) : bool + val aa = a!link(b) + val bb = b!link(a) + val aaa = get(aa) + val bbb = get(bb) + (aaa && bbb) +end +active class Tiling_box + var boxes : [Box] + var futures : [Fut[unit]] + var futs_left : int + def init(agents : [Agent], n : int) : unit + match find_extreme(agents) with + case (xmax, ymax, xmin, ymin) => + val dx = (xmax - xmin) / n + this.boxes = new [Box]( n * n ) + this.futures = new [Fut[unit]](|this.boxes|) + if(n>1) then + var x = xmin + var y = ymin + var i = 0 + var win = true + val dy = (ymax - ymin) / n + for xindex <- [0..n - 2] do + for yindex <- [0..n - 2] do + this.boxes(i) = new Box((x + dx - 1, y + dy - 1), (x, y),n) + if yindex != 0 then + win = win && link((this.boxes)(i), (this.boxes)(i - 1)) + end + if xindex != 0 then + win = win && link((this.boxes)(i), (this.boxes)(i - n)) + end + if xindex != 0 && yindex != 0 then + win = win && link((this.boxes)(i), (this.boxes)(i - n + 1)) + win = win && link((this.boxes)(i), (this.boxes)(i - n - 1)) + () + end + i = i + 1 + y = y + dy + end + this.boxes(i) = new Box((x + dx - 1, ymax), (x, y), n) + if xindex != 0 then + win = win && link((this.boxes)(i), (this.boxes)(i - n)) + win = win && link((this.boxes)(i), (this.boxes)(i - n - 1)) + end + win = win && link((this.boxes)(i), (this.boxes)(i - 1)) + i = i + 1 + x = x + dx + y = ymin + end + for yindex <- [0..n - 2] do + (this.boxes)(i) = new Box((xmax, y + dy - 1), (x, y),n) + if yindex != 0 then + win = win && link((this.boxes)(i), (this.boxes)(i - 1)) + win = win && link((this.boxes)(i), (this.boxes)(i - n - 1)) + end + win = win && link((this.boxes)(i), (this.boxes)(i - n + 1)) + win = win && link((this.boxes)(i), (this.boxes)(i - n)) + i = i + 1 + y = y + dy + end + (this.boxes)(i) = new Box((xmax, ymax), (x, y),n) + win = win && link((this.boxes)(i), (this.boxes)(i - n)) + win = win && link((this.boxes)(i), (this.boxes)(i - 1)) + win = win && link((this.boxes)(i), (this.boxes)(i - n - 1)) + else + this.boxes(0) = new Box((xmax,ymax), (xmin,ymin),n) + end + for a <- agents do + for b <- this.boxes do + if get(b!add(a)) then + break + end + end + end + end + end + end + --move i time steps + def move(i : int) : unit + for id <- [0..|this.boxes| - 1] do + (this.futures)(id) = ((this.boxes)(id)) ! move() + end + for f <- this.futures do + get(f) + end + if i > 1 then + this!move(i - 1) + else + print("DONE") + end + end + -- used by ui, if a ui is used + def agents() : [(int, int)] + val temp = new [[(int, int)]](|this.boxes|) + for i <- [0..|this.boxes| - 1] do + temp(i) = get((this.boxes(i)) ! agents()) + end + flatten(temp) + end +end +active class Box + var xmax : int + var ymax : int + var xmin : int + var ymin : int + var up : Maybe[Box] + var down : Maybe[Box] + var left : Maybe[Box] + var right : Maybe[Box] + var top_right : Maybe[Box] + var top_left : Maybe[Box] + var bottom_left : Maybe[Box] + var bottom_right : Maybe[Box] + var matrix : Quad_tree + var agents : Maybe[Item] + var last : Maybe[Item] + var newcommers : Maybe[Item] + var ttl : int + var size : int + var moving : bool + def init(in_max : (int, int), in_min : (int, int), ttl : int) : unit + this.agents=Nothing + this.last=Nothing + this.newcommers=Nothing + this.up=Nothing + this.down=Nothing + this.left=Nothing + this.right=Nothing + this.top_left=Nothing + this.bottom_right=Nothing + this.bottom_left=Nothing + this.matrix = new Quad_tree(in_max, in_min) + this.top_right=Nothing + match in_max with + case (x, y) => + this.xmax = x + this.ymax = y + end + end + match in_min with + case (x, y) => + this.xmin = x + this.ymin = y + end + end + this.ttl = ttl+1 + this.size = 0 + this.moving = false + end + def min() : (int, int) + (this.xmin, this.ymin) + end + def max() : (int, int) + (this.xmax, this.ymax) + end + + def agents() : [(int, int)] + this.merge() + match this.agents with + case Nothing => new [(int, int)](0) + case thing => + var cur=thing + var i = 0 + while cur != Nothing do + i = i + 1 + match cur with + case Just(thing) => cur=thing.next + end + end + var ret = new [(int, int)](i) + cur = this.agents + i = 0 + while cur != Nothing do + match cur with + case Just(thing) => + cur=thing.next + ret(i) = thing.a.pos() + end + end + i = i + 1 + end + ret + end + end + end + def add(a : Agent) : bool + if a.x > this.xmax || a.x < this.xmin || a.y > this.ymax || a.y < this.ymin then + false + else + this.add_internal(a,a.x,a.y) + true + end + end + def external_move(var a : Agent, x : int, y : int) : Maybe[Agent] + if x > this.xmax || x < this.xmin || y > this.ymax || y < this.ymin then + Just(a) + else + if this.matrix.get_val(x, y) == true then + Just(a) + else + a.move_int(x, y) + this.add_internal(a,x,y) + Nothing + end + end + end + def private add_internal(a : Agent, x : int, y : int) : unit + if this.matrix.get_val(x,y) == true then + abort("AGENTS IN TOP OF eachother\n") + else + this.matrix.set(x,y) + if this.newcommers == Nothing then + this.newcommers = Just(new Item(a)) + else + if this.last == Nothing then + this.last = Just(new Item(a)) + this.yolo_item(this.newcommers).append(this.last) + else + var new_wraper = Just(new Item(a)) + this.yolo_item(this.last).append(new_wraper) + this.last = new_wraper + end + end + this.size = this.size + 1 + end + end + def link(a : Box) : bool + var c = a ! max() + var d = a ! min() + await(c) + await(d) + match (this.xmax, this.ymax, this.xmin, this.ymin, get(c), get(d)) with + case (x_max_1, y_max_1, x_min_1, y_min_1, (x_max_2, y_max_2), (x_min_2, y_min_2)) => + var top = y_max_1 + 1 == y_min_2 + var bottom = y_min_1 - 1 == y_max_2 + var right = x_max_1 + 1 == x_min_2 + var left = x_min_1 - 1 == x_max_2 + var isnull = fun(input : Maybe[Box]) => match input with + case Nothing => true + case unused => false + end + if not(left || right || top || bottom) then + false + else + if top then + if right then + if isnull(this.top_right) then + this.top_right = Just(a) + end + else + if left then + if isnull(this.top_left) then + this.top_left = Just(a) + end + else + if isnull(this.up) then + this.up = Just(a) + end + end + end + else + if bottom then + if right then + if isnull(this.bottom_right) then + this.bottom_right = Just(a) + end + else + if left then + if isnull(this.bottom_left) then + this.bottom_left = Just(a) + end + else + if isnull(this.down) then + this.down = Just(a) + end + end + end + else + if right then + if isnull(this.right) then + this.right = Just(a) + end + else + if isnull(this.left) then + this.left = Just(a) + end + end + end + end + true + end + end + end + end + def private merge() : unit + if this.newcommers != Nothing then + if this.agents != Nothing then + match (this.newcommers,this.last) with + case (unused,Just(last)) => last.append(this.agents) + case (Just(newc),unused) => newc.append(this.agents) + end + this.agents = this.newcommers + else + this.agents = this.newcommers + end + this.newcommers = Nothing + this.last = Nothing + end + end + def private is_something(a:Maybe[Item]) : bool + match a with + case Nothing => false + case unused => true + end + end + def private yolo_item(i : Maybe[Item]) : Item + match i with + case Just(item) => item + end + end + def move() : unit + this.ttl = this.ttl - 1 + this.merge() + var parent = this.agents + var wrapped_a = this.agents + var desired = new [int](6) + while this.is_something(wrapped_a) do + var a = this.yolo_item(wrapped_a) + if a.a.ttl == this.ttl then + a.a.ttl=a.a.ttl - 1 + a.a.next(desired) --get the desired cordnates in format [x1,y1,x2,y2,x3,y3] + var i = 0 + var moved = false + var x2 = 0 + var y2 = 0 + while i < |desired| && moved == false do + val x = desired(i) + val y = desired(i + 1) + let + up = y > this.ymax + down = y < this.ymin + right = x > this.xmax + left = x < this.xmin + border = if up then + if right then + this.top_right + else + if left then + this.top_left + else + this.up + end + end + else + if down then + if right then + this.bottom_right + else + if left then + this.bottom_left + else + this.down + end + end + else + if left then + this.left + else + if right then + this.right + else + Nothing + end + end + end + end + in + var ax = a.a.x + var ay = a.a.y + match border with + case Nothing => + if not(y > this.ymax || y < this.ymin || x > this.xmax || x < this.xmin) && this.matrix.get_val(x, y) == false then + this.matrix.remove(ax, ay) + this.matrix.set(x, y) + a.a.move_int(x, y) + moved = true + end + end + case Just(real_thing) => + x2 = ax + y2 = ay + val first= (wrapped_a == this.agents) + var nejbor = real_thing ! external_move( a.a, x, y) --consume + await(nejbor) + val futurefilled = get(nejbor) + match futurefilled with + case Just(returned_agent) => a.a=returned_agent + case Nothing => + this.size = this.size - 1 + this.matrix.remove(x2, y2) + moved = true + if first then + this.agents = a.next + end + end + end + end + end + i = i + 2 --iterate to next pair of cordnates + end + end + end + wrapped_a = a.next + end + this.moving = false + end +end + +local class Item : Id + var a : Agent + var next : Maybe[Item] + var prev : Maybe[Item] + def init(var a : Agent) : unit + this.a = a --consume(a) + this.next=Nothing + this.prev=Nothing + end + def delete() : unit + match (this.next,this.prev) with + case (Nothing,Nothing) => () + case (Just(next),Just(prev)) => + prev.next=this.next + next.prev=this.prev + end + case (Nothing,Just(prev)) => prev.next=Nothing + case (Just(next),Nothing) => next.prev=Nothing + end + end + def append(next : Maybe[Item]) : unit + this.next = next + match next with + case Nothing => () + case Just(thing) => thing.prev=Just(this) + end + end +end diff --git a/src/tests/stress/pedsim/Ped_util/XML.enc b/src/tests/stress/pedsim/Ped_util/XML.enc new file mode 100644 index 000000000..614bc400f --- /dev/null +++ b/src/tests/stress/pedsim/Ped_util/XML.enc @@ -0,0 +1,230 @@ +{- +WARRNING this is a minimal untested file XML "library" +This should be replaced with standard library functionallity when that is available +-} +module XML +import IO +local class XML_node + var s_rep : String + var children : [XML_node] + var comments : [String] + var name : String + var atribs : [(String, String)] + def init() : unit + () + end + def children_named(name : String) : [XML_node] + var cn = new [XML_node](|this.children|) + var i = 0 + for a <- this.children do + if a.name.contains(name) then + cn(i) = a + i = i + 1 + end + end + var cn2 = new [XML_node](i) + i = 0 + for a <- cn2 do + cn2(i) = cn(i) + i = i + 1 + end + cn2 + end + def attribute_value(name : String) : String + var ret = "" + for a <- this.atribs do + match a with + case (key, value) when key.contains(name) => + ret = value + () + end + case _ => + () + end + + end + end + ret + end +end +local class XML_lib + def init() : unit + () + end + def new_XML_node(s : String) : Maybe[XML_node] + var node = new XML_node() + var error = false + s.trim() + node.s_rep = s + var cont = new [String](s.occurrences("<")) + if |cont| == 1 then + var r = match (s.char_at(0), s.char_at(s.size() - 2), s.char_at(s.size() - 1)) with + case (Just('<'), Just('/'), Just('>')) => + node.name = s + this.ext_atribs(node, node.name) + Just(node) + end + case _ => + Nothing + end + + end + EMBED (unit) + return #{r}; + END + end + var start = s.find("<") + var finish = 0 + for i <- [0..|cont| - 1] do + finish = s.find_from(">", start) + cont(i) = match s.substring(start, finish + 1) with + case Just(sub) => + sub + end + case Nothing => + "" + end + + end + start = s.find_from("<", finish) + end + node.name = cont(0) + this.ext_atribs(node, node.name) + if this.pair(node.name, cont(|cont| - 1)) then + node.comments = new [String](|cont|) + var ci = 0 + var babies = new [String](|cont|) + var j = 0 + var temp = "" + var level = 0 + for i <- [1..|cont| - 2] do + match (level, this.tag_type(cont(i))) with + case (0, 'c') => + (node.comments)(ci) = cont(i) + ci = ci + 1 + () + end + case (0, 't') => + babies(j) = cont(i) + j = j + 1 + () + end + case (1, 'e') => + babies(j) = temp.concatenate(cont(i)) + temp = "" + j = j + 1 + level = 0 + () + end + case (X, 'e') => + temp = temp.concatenate(cont(i)) + level = X - 1 + () + end + case (X, 's') => + temp = temp.concatenate(cont(i)) + level = X + 1 + () + end + case _ => + temp = temp.concatenate(cont(i)) + () + end + end + end + node.children = new [XML_node](j) + for i <- [0..j - 1] do + match this.new_XML_node(babies(i)) with + case Just(xml) => + (node.children)(i) = xml + () + end + case Nothing => + error = true + () + end + end + end + if error == false then + Just(node) + else + Nothing + end + else + Nothing + end + end + def tag_type(s : String) : char + match s.char_at(1) with + case Just('!') => + 'c' + end + case Just('/') => + 'e' + end + case _ => + match s.char_at(s.size() - 2) with + case Just('/') => + 't' + end + case _ => + 's' + end + + end + end + + end + end + def ext_atribs(node : XML_node, s : String) : unit + node.atribs = new [(String, String)](s.occurrences("=")) + var eqsign = 0 + var space = 0 + var value = "" + var key = "" + for i <- [0..|node.atribs| - 1] do + space = s.find_from(" ", eqsign) + eqsign = s.find_from("=", eqsign + 1) + value = match s.substring(eqsign + 2, this.or_find_from(" ", ">", eqsign, s) - 1) with + case Just(derp) => + derp + end + case Nothing => + "MISSFORMEDVALUE" + end + + end + key = match s.substring(space, eqsign) with + case Just(derp) => + derp + end + case Nothing => + "MISSFORMEDKEY" + end + + end + (node.atribs)(i) = (key, value) + end + end + def or_find_from(a : String, b : String, i : int, s : String) : int + var w = s.find_from(a, i) + var q = s.find_from(b, i) + if w < q && w > -(1) then + w + else + q + end + end + def pair(head : String, tail : String) : bool + true + end + def file_to_xml(fname : String) : Maybe[XML_node] + var f = new File("", "") + var s = "" + f.open(fname, "r") + while f.eof() != true do + s = s.concatenate(f.readline()) + end + this.new_XML_node(s) + end +end diff --git a/src/tests/stress/pedsim/README.md b/src/tests/stress/pedsim/README.md new file mode 100644 index 000000000..4179947aa --- /dev/null +++ b/src/tests/stress/pedsim/README.md @@ -0,0 +1,11 @@ +This folder contains the implementation of a pedestrian simulation in Encore. The simulation uses input XML files, which by conventions have the name X_scenario.xml, where X is the number of agents they contain. The various test instances uses different files split into different numbers of regions. + +The benchmark is used like this: + +regions(A,B,S) + +Where A is an array of agents, which can be created by calling parse_file("...") for some valid instance file, B is the square rot of the number of parallel regions to be created, and S is the number of time steps to simulate. + +Note: The number of parallel regions/active-object workers is the input number squared. So regions(agents,3,100) will make 9 workers. + +Author: David Escher diff --git a/src/tests/stress/pedsim/parallel_small.enc b/src/tests/stress/pedsim/parallel_small.enc new file mode 100644 index 000000000..ba3ff8fe6 --- /dev/null +++ b/src/tests/stress/pedsim/parallel_small.enc @@ -0,0 +1,16 @@ +import Ped_util.Global_funs +import Ped_util.Regions +import Ped_util.Quad_tree + + +class Main + def main(args : [String]) : unit + let + agents = parse_file("400_scenario.xml") + boxes = 9 + steps = 10000 + in + regions(agents,boxes,steps) + end + end +end diff --git a/src/tests/stress/pedsim/parallel_small.out b/src/tests/stress/pedsim/parallel_small.out new file mode 100644 index 000000000..c8e8a135c --- /dev/null +++ b/src/tests/stress/pedsim/parallel_small.out @@ -0,0 +1 @@ +DONE diff --git a/src/tests/stress/pedsim/serial_big.enc b/src/tests/stress/pedsim/serial_big.enc new file mode 100644 index 000000000..b0a6a0167 --- /dev/null +++ b/src/tests/stress/pedsim/serial_big.enc @@ -0,0 +1,16 @@ +import Ped_util.Global_funs +import Ped_util.Regions +import Ped_util.Quad_tree + + +class Main + def main(args : [String]) : unit + let + agents = parse_file("16000_scenario.xml") + boxes = 1 + steps = 10000 + in + regions(agents,boxes,steps) + end + end +end diff --git a/src/tests/stress/pedsim/serial_big.out b/src/tests/stress/pedsim/serial_big.out new file mode 100644 index 000000000..c8e8a135c --- /dev/null +++ b/src/tests/stress/pedsim/serial_big.out @@ -0,0 +1 @@ +DONE From 25ecb273363406eea7cb5323f8b4702318680c10 Mon Sep 17 00:00:00 2001 From: Kiko Date: Thu, 1 Jun 2017 00:15:37 +0200 Subject: [PATCH 12/18] cast print (#811) * cast print * fix printing intptr_t * fix to decimal format --- src/runtime/stream/stream.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/runtime/stream/stream.c b/src/runtime/stream/stream.c index f289b7e4f..79260735e 100644 --- a/src/runtime/stream/stream.c +++ b/src/runtime/stream/stream.c @@ -2,6 +2,7 @@ #include "future.h" #include #include +#include struct scons{ bool eos; @@ -55,7 +56,7 @@ __attribute__ ((unused)) static void scons_print(struct scons *scons){ printf("struct scons@%p{\n", scons); printf(" eos = %s\n", scons->eos? "true": "false"); - printf(" element = %ld\n", scons->element.i); + printf(" element = %" PRIdPTR "\n", scons->element.i); printf(" type = %p\n", scons->type); printf(" next = %p\n", scons->next); printf("}\n"); From e8219449077eaf4d6369836c55330fc884835ed3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Casper=20Str=C3=B6mberg?= Date: Fri, 7 Apr 2017 12:08:32 +0200 Subject: [PATCH 13/18] Parsing and input default fields to AST MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit has squashed the following commits into a single one - removing pbcopy - prepare for default values - exprimenterar med seq väldigt nära nu - default field parameters working with bugs - do not desugar field without expression - refactor. adding comments - deacent looking - adding basic test for default params - moving to other class - More tests - testing expressions and adding out - moving - adding test for defaultParameters - removing binary - adding test for finalizer - adding tests for multiple constructors --- src/ir/AST/AST.hs | 3 ++- src/ir/AST/Desugarer.hs | 21 +++++++++++++++++- src/parser/Parser/Parser.hs | 22 +++++++++++++------ .../defaultFieldValues/defaultFieldValues.enc | 14 ++++++++++++ .../defaultFieldValues/defaultFieldValues.out | 2 ++ .../defaultFieldValuesExpr.enc | 19 ++++++++++++++++ .../defaultFieldValuesExpr.out | 1 + .../defaultFieldValuesMain.enc | 8 +++++++ .../defaultFieldValuesMain.out | 2 ++ .../defaultParameters/defaultParameters.enc | 13 +++++++++++ .../defaultParameters/defaultParameters.out | 3 +++ src/tests/encore/finalize/finalize.enc | 15 +++++++++++++ src/tests/encore/finalize/finalize.out | 2 ++ .../multipleConstructors.enc | 16 ++++++++++++++ .../multipleConstructors.out | 2 ++ 15 files changed, 134 insertions(+), 9 deletions(-) create mode 100644 src/tests/encore/defaultFieldValues/defaultFieldValues.enc create mode 100644 src/tests/encore/defaultFieldValues/defaultFieldValues.out create mode 100644 src/tests/encore/defaultFieldValues/defaultFieldValuesExpr.enc create mode 100644 src/tests/encore/defaultFieldValues/defaultFieldValuesExpr.out create mode 100644 src/tests/encore/defaultFieldValues/defaultFieldValuesMain.enc create mode 100644 src/tests/encore/defaultFieldValues/defaultFieldValuesMain.out create mode 100644 src/tests/encore/defaultParameters/defaultParameters.enc create mode 100644 src/tests/encore/defaultParameters/defaultParameters.out create mode 100644 src/tests/encore/finalize/finalize.enc create mode 100644 src/tests/encore/finalize/finalize.out create mode 100644 src/tests/encore/multipleConstructors/multipleConstructors.enc create mode 100644 src/tests/encore/multipleConstructors/multipleConstructors.out diff --git a/src/ir/AST/AST.hs b/src/ir/AST/AST.hs index 2bdb032ad..eabbd227a 100644 --- a/src/ir/AST/AST.hs +++ b/src/ir/AST/AST.hs @@ -424,7 +424,8 @@ data FieldDecl = Field { fmeta :: Meta FieldDecl, fmut :: Mutability, fname :: Name, - ftype :: Type + ftype :: Type, + fexpr :: Maybe Expr } instance Show FieldDecl where diff --git a/src/ir/AST/Desugarer.hs b/src/ir/AST/Desugarer.hs index 7b79c7e7a..79c688534 100644 --- a/src/ir/AST/Desugarer.hs +++ b/src/ir/AST/Desugarer.hs @@ -7,6 +7,7 @@ import AST.PrettyPrinter import AST.Util import Types import Text.Megaparsec +import Data.Maybe import qualified Data.List as List @@ -14,7 +15,7 @@ desugarProgram :: Program -> Program desugarProgram p@(Program{traits, classes, functions}) = p{ traits = map desugarTrait traits, - classes = map desugarClass classes, + classes = map (desugarClass . desugarClassParams) classes, functions = map desugarFunction functions } where @@ -61,6 +62,24 @@ desugarProgram p@(Program{traits, classes, functions}) = desugarClass c@(Class{cmethods}) | isPassive c || isShared c = c{cmethods = map desugarMethod cmethods} + -- Desugar default paramater fields into assignments in the construcor + desugarClassParams c@(Class{cmethods, cfields}) = c{cmethods = map (desugarClassParamsMethod c) cmethods} + + desugarClassParamsMethod c@(Class{cmeta, cmethods, cfields}) m@(Method {mbody, mlocals}) + | isConstructor m = m{mbody = Seq{ + emeta= Meta.meta (Meta.sourcePos cmeta), + eseq= (map paramFieldAssignment $ List.filter (isJust . fexpr) cfields) ++ [mbody] + }} + where + paramFieldAssignment field = Assign {emeta=Meta.meta . Meta.sourcePos . fmeta $ field + ,rhs=fromJust . fexpr $ field + ,lhs=FieldAccess{emeta=Meta.meta. Meta.sourcePos . fmeta $ field + ,name=(fname field) + ,target=VarAccess {emeta=Meta.meta . Meta.sourcePos . fmeta $ field + ,qname=qName "this"}}} + desugarClassParamsMethod _ m = m + + desugarMethod m@(Method {mbody, mlocals}) = m{mbody = desugarExpr mbody ,mlocals = map desugarFunction mlocals} diff --git a/src/parser/Parser/Parser.hs b/src/parser/Parser/Parser.hs index 8e57d6cce..40b578fd8 100644 --- a/src/parser/Parser/Parser.hs +++ b/src/parser/Parser/Parser.hs @@ -792,14 +792,22 @@ mutModifier :: EncParser Mutability mutModifier = (reserved "var" >> return Var) <|> (reserved "val" >> return Val) + fieldDecl :: EncParser FieldDecl -fieldDecl = do - fmeta <- buildMeta - fmut <- mutModifier - fname <- Name <$> identifier - colon - ftype <- typ - returnWithEnd Field{fmeta, fmut, fname, ftype} +fieldDecl = do fmeta <- buildMeta + fmut <- mutModifier + fname <- Name <$> identifier + colon + ftype <- typ + optional $ withLinebreaks $ reservedOp "=" + fexpr <- optional expression + returnwithEnd Field{fmeta + ,fmut + ,fname + ,ftype + ,fexpr + } + paramDecl :: EncParser ParamDecl paramDecl = do diff --git a/src/tests/encore/defaultFieldValues/defaultFieldValues.enc b/src/tests/encore/defaultFieldValues/defaultFieldValues.enc new file mode 100644 index 000000000..2617ae013 --- /dev/null +++ b/src/tests/encore/defaultFieldValues/defaultFieldValues.enc @@ -0,0 +1,14 @@ +active class Main + def main() : unit + new Tester() + end +end +active class Tester + val foo : String = "foo" + val bar : String = "bar" + + def init() : unit + println(this.foo) + println(this.bar) + end +end diff --git a/src/tests/encore/defaultFieldValues/defaultFieldValues.out b/src/tests/encore/defaultFieldValues/defaultFieldValues.out new file mode 100644 index 000000000..a907ec3f4 --- /dev/null +++ b/src/tests/encore/defaultFieldValues/defaultFieldValues.out @@ -0,0 +1,2 @@ +foo +bar \ No newline at end of file diff --git a/src/tests/encore/defaultFieldValues/defaultFieldValuesExpr.enc b/src/tests/encore/defaultFieldValues/defaultFieldValuesExpr.enc new file mode 100644 index 000000000..0d9e41a33 --- /dev/null +++ b/src/tests/encore/defaultFieldValues/defaultFieldValuesExpr.enc @@ -0,0 +1,19 @@ +active class Main + def main() : unit + new Pupil() + end +end + + +fun calcAge() : int + 25 * 2 +end + + +active class Pupil + var age : int = calcAge() + + def init() : unit + println(this.age) + end +end diff --git a/src/tests/encore/defaultFieldValues/defaultFieldValuesExpr.out b/src/tests/encore/defaultFieldValues/defaultFieldValuesExpr.out new file mode 100644 index 000000000..c5b431b6c --- /dev/null +++ b/src/tests/encore/defaultFieldValues/defaultFieldValuesExpr.out @@ -0,0 +1 @@ +50 \ No newline at end of file diff --git a/src/tests/encore/defaultFieldValues/defaultFieldValuesMain.enc b/src/tests/encore/defaultFieldValues/defaultFieldValuesMain.enc new file mode 100644 index 000000000..7fb7fbef4 --- /dev/null +++ b/src/tests/encore/defaultFieldValues/defaultFieldValuesMain.enc @@ -0,0 +1,8 @@ +active class Main + var foo : String = "foo" + var bar : String = "bar" + def main() : unit + println(this.foo) + println(this.bar) + end +end diff --git a/src/tests/encore/defaultFieldValues/defaultFieldValuesMain.out b/src/tests/encore/defaultFieldValues/defaultFieldValuesMain.out new file mode 100644 index 000000000..a907ec3f4 --- /dev/null +++ b/src/tests/encore/defaultFieldValues/defaultFieldValuesMain.out @@ -0,0 +1,2 @@ +foo +bar \ No newline at end of file diff --git a/src/tests/encore/defaultParameters/defaultParameters.enc b/src/tests/encore/defaultParameters/defaultParameters.enc new file mode 100644 index 000000000..ee99f03ec --- /dev/null +++ b/src/tests/encore/defaultParameters/defaultParameters.enc @@ -0,0 +1,13 @@ +active class Main + def main() : unit + println(testAdder(1,2,3)) + println(testAdder(1,2)) + println(testAdder(1)) + end +end + +fun testAdder(a: int, b: int = 0, c: int = 0) : int + a + b + c +end + + diff --git a/src/tests/encore/defaultParameters/defaultParameters.out b/src/tests/encore/defaultParameters/defaultParameters.out new file mode 100644 index 000000000..6910f0b04 --- /dev/null +++ b/src/tests/encore/defaultParameters/defaultParameters.out @@ -0,0 +1,3 @@ +6 +3 +1 \ No newline at end of file diff --git a/src/tests/encore/finalize/finalize.enc b/src/tests/encore/finalize/finalize.enc new file mode 100644 index 000000000..dba678f77 --- /dev/null +++ b/src/tests/encore/finalize/finalize.enc @@ -0,0 +1,15 @@ +active class Main + def main() : unit + new Tester() + end +end + +active class Tester + def init() : unit + println("init") + end + + def finalize() : unit + println("finalize") + end +end diff --git a/src/tests/encore/finalize/finalize.out b/src/tests/encore/finalize/finalize.out new file mode 100644 index 000000000..cc0bbb111 --- /dev/null +++ b/src/tests/encore/finalize/finalize.out @@ -0,0 +1,2 @@ +init +finalize \ No newline at end of file diff --git a/src/tests/encore/multipleConstructors/multipleConstructors.enc b/src/tests/encore/multipleConstructors/multipleConstructors.enc new file mode 100644 index 000000000..5bc61bd3f --- /dev/null +++ b/src/tests/encore/multipleConstructors/multipleConstructors.enc @@ -0,0 +1,16 @@ +active class Main + def main() : unit + new Pupil(25) + new Pupil() + end +end + +active class Pupil + def init(age : int) : unit + println(age) + end + + def init() : unit + println("no age") + end +end diff --git a/src/tests/encore/multipleConstructors/multipleConstructors.out b/src/tests/encore/multipleConstructors/multipleConstructors.out new file mode 100644 index 000000000..c14861df7 --- /dev/null +++ b/src/tests/encore/multipleConstructors/multipleConstructors.out @@ -0,0 +1,2 @@ +25 +no age \ No newline at end of file From 9fcc2c90e441a4974d2412885fcfeb142d66c668 Mon Sep 17 00:00:00 2001 From: Karolina Nikamo Date: Mon, 1 May 2017 20:48:33 +0300 Subject: [PATCH 14/18] started with default parameters --- src/ir/AST/AST.hs | 3 ++- src/ir/AST/Desugarer.hs | 2 +- src/parser/Parser/Parser.hs | 4 +++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/ir/AST/AST.hs b/src/ir/AST/AST.hs index eabbd227a..9aca281d3 100644 --- a/src/ir/AST/AST.hs +++ b/src/ir/AST/AST.hs @@ -451,7 +451,8 @@ data ParamDecl = Param { pmeta :: Meta ParamDecl, pmut :: Mutability, pname :: Name, - ptype :: Type + ptype :: Type, + pdefault :: Maybe Expr } deriving (Show, Eq) instance HasMeta ParamDecl where diff --git a/src/ir/AST/Desugarer.hs b/src/ir/AST/Desugarer.hs index 79c688534..2020ce2dc 100644 --- a/src/ir/AST/Desugarer.hs +++ b/src/ir/AST/Desugarer.hs @@ -43,7 +43,7 @@ desugarProgram p@(Program{traits, classes, functions}) = ,hname=Name "await" ,htype=unitType ,hparams=[awaitParam]} - awaitParam = Param{pmeta, pmut=Val, pname=Name "f", ptype=futureType $ typeVar "_t"} + awaitParam = Param{pmeta, pmut=Val, pname=Name "f", ptype=futureType $ typeVar "_t", pdefault=???} suspend = Method{mmeta ,mimplicit = True ,mheader = suspendHeader diff --git a/src/parser/Parser/Parser.hs b/src/parser/Parser/Parser.hs index 40b578fd8..f7b915153 100644 --- a/src/parser/Parser/Parser.hs +++ b/src/parser/Parser/Parser.hs @@ -818,7 +818,9 @@ paramDecl = do pname <- Name <$> identifier colon ptype <- typ - returnWithEnd Param{pmeta, pmut, pname, ptype} + optional $ reservedOp "=" + pdefault <- optional expression + returnWithEnd Param{pmeta, pmut, pname, ptype, pdefault} patternParamDecl :: EncParser (Expr, Type) patternParamDecl = do From 5b92c0362d3f067987ab1a8c407c117ff7fdd224 Mon Sep 17 00:00:00 2001 From: Lowe Fredriksson Date: Mon, 1 May 2017 22:03:30 +0200 Subject: [PATCH 15/18] pdefault=Nothing in awaitParam to make the compiler compile --- file | Bin 0 -> 155148 bytes file.enc | 9 +++++++++ src/ir/AST/Desugarer.hs | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100755 file create mode 100644 file.enc diff --git a/file b/file new file mode 100755 index 0000000000000000000000000000000000000000..3fbb08295ad48910c0474b3ccec689b84d0da4e2 GIT binary patch literal 155148 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 SS9RI;zw>17oi5!Ej{ILz1KD%{ literal 0 HcmV?d00001 diff --git a/file.enc b/file.enc new file mode 100644 index 000000000..f6ed7903d --- /dev/null +++ b/file.enc @@ -0,0 +1,9 @@ +active class Main + def main() : unit + greet("Karolina") + end +end + +fun greet(name: String = "Karolin") : unit + print(name) +end diff --git a/src/ir/AST/Desugarer.hs b/src/ir/AST/Desugarer.hs index 2020ce2dc..884396018 100644 --- a/src/ir/AST/Desugarer.hs +++ b/src/ir/AST/Desugarer.hs @@ -43,7 +43,7 @@ desugarProgram p@(Program{traits, classes, functions}) = ,hname=Name "await" ,htype=unitType ,hparams=[awaitParam]} - awaitParam = Param{pmeta, pmut=Val, pname=Name "f", ptype=futureType $ typeVar "_t", pdefault=???} + awaitParam = Param{pmeta, pmut=Val, pname=Name "f", ptype=futureType $ typeVar "_t", pdefault=Nothing} suspend = Method{mmeta ,mimplicit = True ,mheader = suspendHeader From 66524765f8a21a9f6987d9122143a64610f80e11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Casper=20Str=C3=B6mberg?= Date: Tue, 2 May 2017 11:25:04 +0200 Subject: [PATCH 16/18] initial impl. of default params working MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - myser lite - funkar lite gran sådär - chaning test - working for functions - testar lite - got first part, (method decl) of default paramaters for methods working. ie this.test1() --- file | Bin 155148 -> 159644 bytes file.enc | 13 ++-- src/ir/AST/Desugarer.hs | 134 +++++++++++++++++++++++++++++++++++++--- 3 files changed, 135 insertions(+), 12 deletions(-) diff --git a/file b/file index 3fbb08295ad48910c0474b3ccec689b84d0da4e2..c7fd25d6bbf05947b4c99b1e97543391c6b98e32 100755 GIT binary patch literal 159644 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 literal 155148 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 SS9RI;zw>17oi5!Ej{ILz1KD%{ diff --git a/file.enc b/file.enc index f6ed7903d..058892ba8 100644 --- a/file.enc +++ b/file.enc @@ -1,9 +1,14 @@ -active class Main +active class Main def main() : unit - greet("Karolina") + this.test1(20) + end + + def test(x : int, y : int = 30) : unit + println(y) end end -fun greet(name: String = "Karolin") : unit - print(name) +fun greet(base : int, age : int = 20) : int + age end + diff --git a/src/ir/AST/Desugarer.hs b/src/ir/AST/Desugarer.hs index 884396018..16d39082d 100644 --- a/src/ir/AST/Desugarer.hs +++ b/src/ir/AST/Desugarer.hs @@ -8,24 +8,136 @@ import AST.Util import Types import Text.Megaparsec import Data.Maybe - +import Debug.Trace import qualified Data.List as List + + +findFunction :: QualifiedName -> [Function] -> Maybe Function +findFunction qname functions = List.find (\e -> ((show (functionName e)) == (show qname))) functions + +nameForArg :: Int -> String +nameForArg 0 = "" +nameForArg x = show x + +desugarDefaultParamatersCallWithFunction :: Expr -> Function -> Expr +desugarDefaultParamatersCallWithFunction fc@(FunctionCall{qname, args}) fun@(Function{}) = + if isDefaultValid then fc{qname = qName ((show qname) ++ (traceId (nameForArg numOfDefaultParamsUsed)) ) } else fc + where + numOfDefaultParamsUsed = (length (functionParams fun)) - (length args) + isDefaultValid = (numOfDefaultParamsUsed <= (length (List.filter (isJust . pdefault) (functionParams fun)))) && ((length args) <= (length (functionParams fun))) + + +desugarDefaultParamatersCall :: Program -> Expr -> Expr +desugarDefaultParamatersCall p@(Program{functions}) fc@(FunctionCall{qname, args}) = + case (findFunction qname functions) of Just function -> desugarDefaultParamatersCallWithFunction fc function + _ -> fc +desugarDefaultParamatersCall _ expr = expr + +createFunction :: Function -> [Expr] -> Function +createFunction func@(Function{funheader}) defaultParams = + func{funheader=Header{ + hmodifiers= hmodifiers funheader, + kind= kind funheader, + htypeparams= take usedParams (htypeparams funheader), + hname=Name (show (hname funheader) ++ show (length defaultParams)), + htype= htype funheader, + hparams= params + }, + funbody=Return {emeta= Meta.meta $ Meta.sourcePos $ funmeta func, + val= FunctionCall{ + emeta=Meta.meta $ Meta.sourcePos $ funmeta func, + typeArguments=htypeparams funheader, + qname= qName $ show $ hname funheader, + args= map (\e -> VarAccess{emeta = Meta.meta $ Meta.sourcePos $ pmeta e, qname = qName $ show $ pname e}) params ++ defaultParams + }} + + } + where + usedParams = ((length (hparams funheader)) - (length defaultParams)) + params = take ((length (hparams funheader)) - (length defaultParams)) (hparams funheader) + +desugarFunctionHeader :: Function -> [Expr] -> [Function] +desugarFunctionHeader f [] = [] +desugarFunctionHeader f params@(_:xs) = desugarFunctionHeader f xs ++ [createFunction f params] + + + + + + +desugarDefaultParamaters :: Function -> [Function] +desugarDefaultParamaters func = desugarFunctionHeader func defaultParams + where + defaultParams = map (fromJust . pdefault) (List.filter (\p@(Param{pdefault}) -> isJust pdefault) (hparams (funheader func))) + + +-- create a method with default headers filled in +createMethod :: AST.AST.MethodDecl -> [Expr] -> AST.AST.MethodDecl +createMethod meth@(Method{mheader, mmeta}) defaultParams = + meth{mheader=Header{ + hmodifiers= hmodifiers mheader, + kind= kind mheader, + htypeparams= take usedParams (htypeparams mheader), + hname=Name (show (hname mheader) ++ show (length defaultParams)), + htype= htype mheader, + hparams= params + }, + mbody=Return {emeta= Meta.meta $ Meta.sourcePos $ mmeta, + val= MethodCall{ + emeta=Meta.meta $ Meta.sourcePos $ mmeta, + target=VarAccess {emeta=Meta.meta $ Meta.sourcePos $ mmeta, qname=qName "this"}, + typeArguments=htypeparams mheader, + name= hname mheader, + args= map (\e -> VarAccess{emeta = Meta.meta $ Meta.sourcePos $ pmeta e, qname = qName $ show $ pname e}) params ++ defaultParams + }} + + } + where + usedParams = ((length (hparams mheader)) - (length defaultParams)) + params = take ((length (hparams mheader)) - (length defaultParams)) (hparams mheader) + + + + + +desugarDefaultParamatersMethod :: MethodDecl -> [Expr] -> [MethodDecl] +desugarDefaultParamatersMethod f [] = [] +desugarDefaultParamatersMethod f params@(_:xs) = desugarDefaultParamatersMethod f xs ++ [createMethod f params] + + +desugarDefaultParamatersM :: MethodDecl -> [MethodDecl] +desugarDefaultParamatersM m = desugarDefaultParamatersMethod m defaultParams + where + defaultParams = map (fromJust . pdefault) (List.filter (\p@(Param{pdefault}) -> isJust pdefault) (hparams (mheader m))) + + +desugarDefaultParamatersClass :: Program -> ClassDecl -> ClassDecl +desugarDefaultParamatersClass p c@(Class{cmethods}) = c{cmethods = cmethods ++ concat (map desugarDefaultParamatersM cmethods) } + + + +-- desugarDefaultParamatersMethod :: Program -> Method -> [Method] +-- desugarDefaultParamatersMethod p @m(MethodDecl{mheader}) + desugarProgram :: Program -> Program desugarProgram p@(Program{traits, classes, functions}) = p{ traits = map desugarTrait traits, - classes = map (desugarClass . desugarClassParams) classes, - functions = map desugarFunction functions + classes = map (desugarClass . desugarClassParams . (desugarDefaultParamatersClass p)) classes, + functions = (map desugarFunction functions) ++ concat (map desugarDefaultParamaters functions) } where - desugarTrait t@Trait{tmethods}= - t{tmethods = map desugarMethod tmethods} - desugarFunction f@(Function{funbody - ,funlocals}) = - f{funbody = desugarExpr funbody + + desugarTrait t@Trait{tmethods} = t{tmethods = map desugarMethod tmethods} + + desugarFunction f@(Function{funbody,funlocals}) = + f{ + funbody = desugarExpr funbody ,funlocals = map desugarFunction funlocals} + desugarFunctionHeader fh@(Header{hname, hparams}) = + fh{hname = Name (show hname ++ show (length hparams))} -- Automatically give await and supend to active classes -- Then the Actor trait is in place, this desugaring step will be changed -- so that the Actor trait is included instead @@ -90,6 +202,7 @@ desugarProgram p@(Program{traits, classes, functions}) = desugarExpr = extend removeDeadMiniLet . extend desugar . extend optionalAccess . + extend (desugarDefaultParamatersCall p). extend selfSugar -- | Desugars the notation `x?.foo()` and `actor?!bar()` into @@ -257,6 +370,7 @@ desugar FunctionCall{emeta, qname = QName{qnlocal = Name "assertFalse"} Exit (cloneMeta emeta) [IntLiteral (cloneMeta emeta) 1]]) (Skip (cloneMeta emeta)) + -- If-expressions without else desugar IfThen{emeta, cond, thn} = IfThenElse{emeta @@ -377,9 +491,13 @@ desugar f@FunctionCall{emeta, qname = QName{qnlocal = Name "Just"} ,args = [arg]} = MaybeValue{emeta, mdt = JustData arg} + + desugar e = e assertionFailed emeta assert = StringLiteral (cloneMeta emeta) $ "Assertion failed at " ++ Meta.showPos emeta ++ ":\n" ++ assert + + From 6785ba6486efb5f282d2eaa6c7dc22f1a02760ba Mon Sep 17 00:00:00 2001 From: Karolina Nikamo Date: Tue, 9 May 2017 15:10:39 +0200 Subject: [PATCH 17/18] desugar method calls, default params and fixes This commit has squashed the following commits: - default params for methods fixed - default params for function does not work - default params for functions working - added tests for default params - string as default param in function fixed - removed finalize- and multipleInits-tests - default paramters for local functions fixed - removed a comment - added a test for object as default parameter - edited test for object as default parameter - added test for default field values in a class without an init method - removed comment - git fix - default field values works for class without init - removed files - small fixes --- file | Bin 159644 -> 0 bytes file.enc | 14 --- src/ir/AST/AST.hs | 3 + src/ir/AST/Desugarer.hs | 101 ++++++------------ src/opt/Optimizer/Optimizer.hs | 3 +- src/parser/Parser/Parser.hs | 2 +- .../defaultFieldValuesWithoutInit.enc | 16 +++ .../defaultFieldValuesWithoutInit.out | 2 + .../defaultParameters/defaultParameters.enc | 13 --- .../defaultParameters/defaultParameters.out | 3 - .../defaultParametersFunc.enc | 13 +++ .../defaultParametersFunc.out | 9 ++ .../defaultParametersFuncLocal.enc | 13 +++ .../defaultParametersFuncLocal.out | 9 ++ .../defaultParametersMeth.enc | 19 ++++ .../defaultParametersMeth.out | 9 ++ .../defaultParametersMeth2.enc | 16 +++ .../defaultParametersMeth2.out | 9 ++ .../defaultParametersObject.enc | 30 ++++++ .../defaultParametersObject.out | 9 ++ src/tests/encore/finalize/finalize.enc | 15 --- src/tests/encore/finalize/finalize.out | 2 - .../multipleConstructors.enc | 16 --- .../multipleConstructors.out | 2 - src/types/Typechecker/Typechecker.hs | 47 +++++--- 25 files changed, 227 insertions(+), 148 deletions(-) delete mode 100755 file delete mode 100644 file.enc create mode 100644 src/tests/encore/defaultFieldValues/defaultFieldValuesWithoutInit.enc create mode 100644 src/tests/encore/defaultFieldValues/defaultFieldValuesWithoutInit.out delete mode 100644 src/tests/encore/defaultParameters/defaultParameters.enc delete mode 100644 src/tests/encore/defaultParameters/defaultParameters.out create mode 100644 src/tests/encore/defaultParameters/defaultParametersFunc.enc create mode 100644 src/tests/encore/defaultParameters/defaultParametersFunc.out create mode 100644 src/tests/encore/defaultParameters/defaultParametersFuncLocal.enc create mode 100644 src/tests/encore/defaultParameters/defaultParametersFuncLocal.out create mode 100644 src/tests/encore/defaultParameters/defaultParametersMeth.enc create mode 100644 src/tests/encore/defaultParameters/defaultParametersMeth.out create mode 100644 src/tests/encore/defaultParameters/defaultParametersMeth2.enc create mode 100644 src/tests/encore/defaultParameters/defaultParametersMeth2.out create mode 100644 src/tests/encore/defaultParameters/defaultParametersObject.enc create mode 100644 src/tests/encore/defaultParameters/defaultParametersObject.out delete mode 100644 src/tests/encore/finalize/finalize.enc delete mode 100644 src/tests/encore/finalize/finalize.out delete mode 100644 src/tests/encore/multipleConstructors/multipleConstructors.enc delete mode 100644 src/tests/encore/multipleConstructors/multipleConstructors.out diff --git a/file b/file deleted file mode 100755 index c7fd25d6bbf05947b4c99b1e97543391c6b98e32..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 159644 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 diff --git a/file.enc b/file.enc deleted file mode 100644 index 058892ba8..000000000 --- a/file.enc +++ /dev/null @@ -1,14 +0,0 @@ -active class Main - def main() : unit - this.test1(20) - end - - def test(x : int, y : int = 30) : unit - println(y) - end -end - -fun greet(base : int, age : int = 20) : int - age -end - diff --git a/src/ir/AST/AST.hs b/src/ir/AST/AST.hs index 9aca281d3..2f4487613 100644 --- a/src/ir/AST/AST.hs +++ b/src/ir/AST/AST.hs @@ -485,6 +485,9 @@ isConstructor m = methodName m == constructorName isImplicitMethod = mimplicit +hasConstructor :: ClassDecl -> Bool +hasConstructor Class{cmethods} = filter isConstructor cmethods /= [] + emptyConstructor :: ClassDecl -> MethodDecl emptyConstructor cdecl = let pos = AST.AST.getPos cdecl diff --git a/src/ir/AST/Desugarer.hs b/src/ir/AST/Desugarer.hs index 16d39082d..f2966c3e7 100644 --- a/src/ir/AST/Desugarer.hs +++ b/src/ir/AST/Desugarer.hs @@ -8,68 +8,41 @@ import AST.Util import Types import Text.Megaparsec import Data.Maybe -import Debug.Trace import qualified Data.List as List - -findFunction :: QualifiedName -> [Function] -> Maybe Function -findFunction qname functions = List.find (\e -> ((show (functionName e)) == (show qname))) functions - -nameForArg :: Int -> String -nameForArg 0 = "" -nameForArg x = show x - -desugarDefaultParamatersCallWithFunction :: Expr -> Function -> Expr -desugarDefaultParamatersCallWithFunction fc@(FunctionCall{qname, args}) fun@(Function{}) = - if isDefaultValid then fc{qname = qName ((show qname) ++ (traceId (nameForArg numOfDefaultParamsUsed)) ) } else fc - where - numOfDefaultParamsUsed = (length (functionParams fun)) - (length args) - isDefaultValid = (numOfDefaultParamsUsed <= (length (List.filter (isJust . pdefault) (functionParams fun)))) && ((length args) <= (length (functionParams fun))) - - -desugarDefaultParamatersCall :: Program -> Expr -> Expr -desugarDefaultParamatersCall p@(Program{functions}) fc@(FunctionCall{qname, args}) = - case (findFunction qname functions) of Just function -> desugarDefaultParamatersCallWithFunction fc function - _ -> fc -desugarDefaultParamatersCall _ expr = expr - createFunction :: Function -> [Expr] -> Function createFunction func@(Function{funheader}) defaultParams = func{funheader=Header{ hmodifiers= hmodifiers funheader, kind= kind funheader, htypeparams= take usedParams (htypeparams funheader), - hname=Name (show (hname funheader) ++ show (length defaultParams)), + hname=Name ("_" ++ show (hname funheader) ++ show (length defaultParams)), htype= htype funheader, hparams= params }, - funbody=Return {emeta= Meta.meta $ Meta.sourcePos $ funmeta func, + funbody=Return {emeta= Meta.meta $ Meta.getPos $ funmeta func, val= FunctionCall{ - emeta=Meta.meta $ Meta.sourcePos $ funmeta func, + emeta=Meta.meta $ Meta.getPos $ funmeta func, typeArguments=htypeparams funheader, qname= qName $ show $ hname funheader, - args= map (\e -> VarAccess{emeta = Meta.meta $ Meta.sourcePos $ pmeta e, qname = qName $ show $ pname e}) params ++ defaultParams + args= map (\e -> VarAccess{emeta = Meta.meta $ Meta.getPos $ pmeta e, qname = qName $ show $ pname e}) params ++ defaultParams }} - } where usedParams = ((length (hparams funheader)) - (length defaultParams)) params = take ((length (hparams funheader)) - (length defaultParams)) (hparams funheader) + desugarFunctionHeader :: Function -> [Expr] -> [Function] desugarFunctionHeader f [] = [] desugarFunctionHeader f params@(_:xs) = desugarFunctionHeader f xs ++ [createFunction f params] - - - - -desugarDefaultParamaters :: Function -> [Function] -desugarDefaultParamaters func = desugarFunctionHeader func defaultParams +desugarDefaultParameters :: Function -> [Function] +desugarDefaultParameters func = desugarFunctionHeader func defaultParams where - defaultParams = map (fromJust . pdefault) (List.filter (\p@(Param{pdefault}) -> isJust pdefault) (hparams (funheader func))) + defaultParams = map (desugar . fromJust . pdefault) (List.filter (\p@(Param{pdefault}) -> isJust pdefault) (hparams (funheader func))) -- create a method with default headers filled in @@ -79,17 +52,17 @@ createMethod meth@(Method{mheader, mmeta}) defaultParams = hmodifiers= hmodifiers mheader, kind= kind mheader, htypeparams= take usedParams (htypeparams mheader), - hname=Name (show (hname mheader) ++ show (length defaultParams)), + hname=Name ("_" ++ show (hname mheader) ++ show (length defaultParams)), htype= htype mheader, hparams= params }, - mbody=Return {emeta= Meta.meta $ Meta.sourcePos $ mmeta, + mbody=Return {emeta= Meta.meta $ Meta.getPos $ mmeta, val= MethodCall{ - emeta=Meta.meta $ Meta.sourcePos $ mmeta, - target=VarAccess {emeta=Meta.meta $ Meta.sourcePos $ mmeta, qname=qName "this"}, + emeta=Meta.meta $ Meta.getPos $ mmeta, + target=VarAccess {emeta=Meta.meta $ Meta.getPos $ mmeta, qname=qName "this"}, typeArguments=htypeparams mheader, name= hname mheader, - args= map (\e -> VarAccess{emeta = Meta.meta $ Meta.sourcePos $ pmeta e, qname = qName $ show $ pname e}) params ++ defaultParams + args= map (\e -> VarAccess{emeta = Meta.meta $ Meta.getPos $ pmeta e, qname = qName $ show $ pname e}) params ++ defaultParams }} } @@ -99,33 +72,27 @@ createMethod meth@(Method{mheader, mmeta}) defaultParams = +desugarDefaultParametersMethod :: MethodDecl -> [Expr] -> [MethodDecl] +desugarDefaultParametersMethod f [] = [] +desugarDefaultParametersMethod f params@(_:xs) = desugarDefaultParametersMethod f xs ++ [createMethod f params] -desugarDefaultParamatersMethod :: MethodDecl -> [Expr] -> [MethodDecl] -desugarDefaultParamatersMethod f [] = [] -desugarDefaultParamatersMethod f params@(_:xs) = desugarDefaultParamatersMethod f xs ++ [createMethod f params] - - -desugarDefaultParamatersM :: MethodDecl -> [MethodDecl] -desugarDefaultParamatersM m = desugarDefaultParamatersMethod m defaultParams +desugarDefaultParametersM :: MethodDecl -> [MethodDecl] +desugarDefaultParametersM m = desugarDefaultParametersMethod m defaultParams where defaultParams = map (fromJust . pdefault) (List.filter (\p@(Param{pdefault}) -> isJust pdefault) (hparams (mheader m))) -desugarDefaultParamatersClass :: Program -> ClassDecl -> ClassDecl -desugarDefaultParamatersClass p c@(Class{cmethods}) = c{cmethods = cmethods ++ concat (map desugarDefaultParamatersM cmethods) } +desugarDefaultParametersClass :: Program -> ClassDecl -> ClassDecl +desugarDefaultParametersClass p c@(Class{cmethods}) = c{cmethods = cmethods ++ concat (map desugarDefaultParametersM cmethods) } - --- desugarDefaultParamatersMethod :: Program -> Method -> [Method] --- desugarDefaultParamatersMethod p @m(MethodDecl{mheader}) - desugarProgram :: Program -> Program desugarProgram p@(Program{traits, classes, functions}) = p{ traits = map desugarTrait traits, - classes = map (desugarClass . desugarClassParams . (desugarDefaultParamatersClass p)) classes, - functions = (map desugarFunction functions) ++ concat (map desugarDefaultParamaters functions) + classes = map (desugarClass . desugarClassParams . (desugarDefaultParametersClass p)) classes, + functions = (map desugarFunction functions) ++ concat (map desugarDefaultParameters functions) } where @@ -134,10 +101,8 @@ desugarProgram p@(Program{traits, classes, functions}) = desugarFunction f@(Function{funbody,funlocals}) = f{ funbody = desugarExpr funbody - ,funlocals = map desugarFunction funlocals} + ,funlocals = (map desugarFunction funlocals) ++ concat (map desugarDefaultParameters funlocals)} - desugarFunctionHeader fh@(Header{hname, hparams}) = - fh{hname = Name (show hname ++ show (length hparams))} -- Automatically give await and supend to active classes -- Then the Actor trait is in place, this desugaring step will be changed -- so that the Actor trait is included instead @@ -174,27 +139,30 @@ desugarProgram p@(Program{traits, classes, functions}) = desugarClass c@(Class{cmethods}) | isPassive c || isShared c = c{cmethods = map desugarMethod cmethods} - -- Desugar default paramater fields into assignments in the construcor - desugarClassParams c@(Class{cmethods, cfields}) = c{cmethods = map (desugarClassParamsMethod c) cmethods} + -- Desugar default Parameter fields into assignments in the construcor + desugarClassParams c@(Class{cmethods, cfields}) = c{cmethods = map (desugarClassParamsMethod c) (cmethods ++ createConstructor c)} + + createConstructor c = if hasConstructor c then [] + else [emptyConstructor c] desugarClassParamsMethod c@(Class{cmeta, cmethods, cfields}) m@(Method {mbody, mlocals}) | isConstructor m = m{mbody = Seq{ - emeta= Meta.meta (Meta.sourcePos cmeta), + emeta= Meta.meta (Meta.getPos cmeta), eseq= (map paramFieldAssignment $ List.filter (isJust . fexpr) cfields) ++ [mbody] }} where - paramFieldAssignment field = Assign {emeta=Meta.meta . Meta.sourcePos . fmeta $ field + paramFieldAssignment field = Assign {emeta=Meta.meta . Meta.getPos . fmeta $ field ,rhs=fromJust . fexpr $ field - ,lhs=FieldAccess{emeta=Meta.meta. Meta.sourcePos . fmeta $ field + ,lhs=FieldAccess{emeta=Meta.meta. Meta.getPos . fmeta $ field ,name=(fname field) - ,target=VarAccess {emeta=Meta.meta . Meta.sourcePos . fmeta $ field + ,target=VarAccess {emeta=Meta.meta . Meta.getPos . fmeta $ field ,qname=qName "this"}}} desugarClassParamsMethod _ m = m desugarMethod m@(Method {mbody, mlocals}) = m{mbody = desugarExpr mbody - ,mlocals = map desugarFunction mlocals} + ,mlocals = map desugarFunction mlocals ++ concat (map desugarDefaultParameters mlocals)} -- NOTE: -- `selfSugar` should always be the first desugaring to run. @@ -202,7 +170,6 @@ desugarProgram p@(Program{traits, classes, functions}) = desugarExpr = extend removeDeadMiniLet . extend desugar . extend optionalAccess . - extend (desugarDefaultParamatersCall p). extend selfSugar -- | Desugars the notation `x?.foo()` and `actor?!bar()` into @@ -499,5 +466,3 @@ assertionFailed emeta assert = StringLiteral (cloneMeta emeta) $ "Assertion failed at " ++ Meta.showPos emeta ++ ":\n" ++ assert - - diff --git a/src/opt/Optimizer/Optimizer.hs b/src/opt/Optimizer/Optimizer.hs index 456e7300c..2b9fe71e6 100644 --- a/src/opt/Optimizer/Optimizer.hs +++ b/src/opt/Optimizer/Optimizer.hs @@ -153,6 +153,7 @@ forwardGeneral = extend forwardGeneral' pdecl = Param {pmeta=Meta.setType paramType (Meta.meta (Meta.getPos emeta)) ,pmut =Val ,pname=Name "_id_fun_tmp" - ,ptype=paramType} + ,ptype=paramType + ,pdefault= Nothing} forwardGeneral' e = e diff --git a/src/parser/Parser/Parser.hs b/src/parser/Parser/Parser.hs index f7b915153..a7101eda3 100644 --- a/src/parser/Parser/Parser.hs +++ b/src/parser/Parser/Parser.hs @@ -801,7 +801,7 @@ fieldDecl = do fmeta <- buildMeta ftype <- typ optional $ withLinebreaks $ reservedOp "=" fexpr <- optional expression - returnwithEnd Field{fmeta + returnWithEnd Field{fmeta ,fmut ,fname ,ftype diff --git a/src/tests/encore/defaultFieldValues/defaultFieldValuesWithoutInit.enc b/src/tests/encore/defaultFieldValues/defaultFieldValuesWithoutInit.enc new file mode 100644 index 000000000..cebbf4223 --- /dev/null +++ b/src/tests/encore/defaultFieldValues/defaultFieldValuesWithoutInit.enc @@ -0,0 +1,16 @@ +active class Main + def main() : unit + var t = new Tester() + t!printSelf() + end +end + +active class Tester + val foo : String = "foo" + val bar : String = "bar" + + def printSelf() : unit + println(this.foo) + println(this.bar) + end +end diff --git a/src/tests/encore/defaultFieldValues/defaultFieldValuesWithoutInit.out b/src/tests/encore/defaultFieldValues/defaultFieldValuesWithoutInit.out new file mode 100644 index 000000000..a907ec3f4 --- /dev/null +++ b/src/tests/encore/defaultFieldValues/defaultFieldValuesWithoutInit.out @@ -0,0 +1,2 @@ +foo +bar \ No newline at end of file diff --git a/src/tests/encore/defaultParameters/defaultParameters.enc b/src/tests/encore/defaultParameters/defaultParameters.enc deleted file mode 100644 index ee99f03ec..000000000 --- a/src/tests/encore/defaultParameters/defaultParameters.enc +++ /dev/null @@ -1,13 +0,0 @@ -active class Main - def main() : unit - println(testAdder(1,2,3)) - println(testAdder(1,2)) - println(testAdder(1)) - end -end - -fun testAdder(a: int, b: int = 0, c: int = 0) : int - a + b + c -end - - diff --git a/src/tests/encore/defaultParameters/defaultParameters.out b/src/tests/encore/defaultParameters/defaultParameters.out deleted file mode 100644 index 6910f0b04..000000000 --- a/src/tests/encore/defaultParameters/defaultParameters.out +++ /dev/null @@ -1,3 +0,0 @@ -6 -3 -1 \ No newline at end of file diff --git a/src/tests/encore/defaultParameters/defaultParametersFunc.enc b/src/tests/encore/defaultParameters/defaultParametersFunc.enc new file mode 100644 index 000000000..6dba2a652 --- /dev/null +++ b/src/tests/encore/defaultParameters/defaultParametersFunc.enc @@ -0,0 +1,13 @@ +active class Main + def main() : unit + test(1) + test(2, "hello") + test(3, "world", 4) + end +end + +fun test(a: int, b:String = "b", c: int = 0) : unit + println(a) + println(b) + println(c) +end diff --git a/src/tests/encore/defaultParameters/defaultParametersFunc.out b/src/tests/encore/defaultParameters/defaultParametersFunc.out new file mode 100644 index 000000000..7de9ec9ff --- /dev/null +++ b/src/tests/encore/defaultParameters/defaultParametersFunc.out @@ -0,0 +1,9 @@ +1 +b +0 +2 +hello +0 +3 +world +4 diff --git a/src/tests/encore/defaultParameters/defaultParametersFuncLocal.enc b/src/tests/encore/defaultParameters/defaultParametersFuncLocal.enc new file mode 100644 index 000000000..484640e45 --- /dev/null +++ b/src/tests/encore/defaultParameters/defaultParametersFuncLocal.enc @@ -0,0 +1,13 @@ +active class Main + def main() : unit + bar(1) + bar(2, "hello") + bar(3, "world", 4) + where + fun bar(a: int, b:String = "b", c:int = 0) : unit + println(a) + println(b) + println(c) + end + end +end diff --git a/src/tests/encore/defaultParameters/defaultParametersFuncLocal.out b/src/tests/encore/defaultParameters/defaultParametersFuncLocal.out new file mode 100644 index 000000000..7de9ec9ff --- /dev/null +++ b/src/tests/encore/defaultParameters/defaultParametersFuncLocal.out @@ -0,0 +1,9 @@ +1 +b +0 +2 +hello +0 +3 +world +4 diff --git a/src/tests/encore/defaultParameters/defaultParametersMeth.enc b/src/tests/encore/defaultParameters/defaultParametersMeth.enc new file mode 100644 index 000000000..3cd749404 --- /dev/null +++ b/src/tests/encore/defaultParameters/defaultParametersMeth.enc @@ -0,0 +1,19 @@ +active class Main + def main() : unit + new Tester() + end +end + +active class Tester + def init() : unit + this.foo(1) + this.foo(2, "hello") + this.foo(3, "world", 4) + end + + def foo(a: int, b:String = "b", c:int = 0) : unit + println(a) + println(b) + println(c) + end +end diff --git a/src/tests/encore/defaultParameters/defaultParametersMeth.out b/src/tests/encore/defaultParameters/defaultParametersMeth.out new file mode 100644 index 000000000..7de9ec9ff --- /dev/null +++ b/src/tests/encore/defaultParameters/defaultParametersMeth.out @@ -0,0 +1,9 @@ +1 +b +0 +2 +hello +0 +3 +world +4 diff --git a/src/tests/encore/defaultParameters/defaultParametersMeth2.enc b/src/tests/encore/defaultParameters/defaultParametersMeth2.enc new file mode 100644 index 000000000..66d19bd8b --- /dev/null +++ b/src/tests/encore/defaultParameters/defaultParametersMeth2.enc @@ -0,0 +1,16 @@ +active class Main + def main() : unit + var t = new Tester() + t!foo(1) + t!foo(2, "hello") + t!foo(3, "world", 4) + end +end + +active class Tester + def foo(a: int, b:String = "b", c:int = 0) : unit + println(a) + println(b) + println(c) + end +end diff --git a/src/tests/encore/defaultParameters/defaultParametersMeth2.out b/src/tests/encore/defaultParameters/defaultParametersMeth2.out new file mode 100644 index 000000000..7de9ec9ff --- /dev/null +++ b/src/tests/encore/defaultParameters/defaultParametersMeth2.out @@ -0,0 +1,9 @@ +1 +b +0 +2 +hello +0 +3 +world +4 diff --git a/src/tests/encore/defaultParameters/defaultParametersObject.enc b/src/tests/encore/defaultParameters/defaultParametersObject.enc new file mode 100644 index 000000000..b28c64928 --- /dev/null +++ b/src/tests/encore/defaultParameters/defaultParametersObject.enc @@ -0,0 +1,30 @@ +active class Main + def main() : unit + new Tester() + end +end + +active class Tester + def init() : unit + this.foo(1) + this.foo(2, new Tester2("hello")) + this.foo(3, new Tester2("world"), 4) + end + + def foo(a: int, b:Tester2 = new Tester2("b"), c:int = 0) : unit + println(a) + println(b.bar()) + println(c) + end +end + +local class Tester2 + var b : String + def init(b: String) : unit + this.b = b + end + + def bar() : String + this.b + end +end diff --git a/src/tests/encore/defaultParameters/defaultParametersObject.out b/src/tests/encore/defaultParameters/defaultParametersObject.out new file mode 100644 index 000000000..7de9ec9ff --- /dev/null +++ b/src/tests/encore/defaultParameters/defaultParametersObject.out @@ -0,0 +1,9 @@ +1 +b +0 +2 +hello +0 +3 +world +4 diff --git a/src/tests/encore/finalize/finalize.enc b/src/tests/encore/finalize/finalize.enc deleted file mode 100644 index dba678f77..000000000 --- a/src/tests/encore/finalize/finalize.enc +++ /dev/null @@ -1,15 +0,0 @@ -active class Main - def main() : unit - new Tester() - end -end - -active class Tester - def init() : unit - println("init") - end - - def finalize() : unit - println("finalize") - end -end diff --git a/src/tests/encore/finalize/finalize.out b/src/tests/encore/finalize/finalize.out deleted file mode 100644 index cc0bbb111..000000000 --- a/src/tests/encore/finalize/finalize.out +++ /dev/null @@ -1,2 +0,0 @@ -init -finalize \ No newline at end of file diff --git a/src/tests/encore/multipleConstructors/multipleConstructors.enc b/src/tests/encore/multipleConstructors/multipleConstructors.enc deleted file mode 100644 index 5bc61bd3f..000000000 --- a/src/tests/encore/multipleConstructors/multipleConstructors.enc +++ /dev/null @@ -1,16 +0,0 @@ -active class Main - def main() : unit - new Pupil(25) - new Pupil() - end -end - -active class Pupil - def init(age : int) : unit - println(age) - end - - def init() : unit - println("no age") - end -end diff --git a/src/tests/encore/multipleConstructors/multipleConstructors.out b/src/tests/encore/multipleConstructors/multipleConstructors.out deleted file mode 100644 index c14861df7..000000000 --- a/src/tests/encore/multipleConstructors/multipleConstructors.out +++ /dev/null @@ -1,2 +0,0 @@ -25 -no age \ No newline at end of file diff --git a/src/types/Typechecker/Typechecker.hs b/src/types/Typechecker/Typechecker.hs index 45df82175..a2050f18b 100644 --- a/src/types/Typechecker/Typechecker.hs +++ b/src/types/Typechecker/Typechecker.hs @@ -182,15 +182,24 @@ instance Checkable FieldDecl where return f -matchArgumentLength :: Type -> FunctionHeader -> Arguments -> TypecheckM () +matchArgumentLength :: Type -> FunctionHeader -> Arguments -> TypecheckM Name matchArgumentLength targetType header args = - unless (actual == expected) $ - tcError $ WrongNumberOfMethodArgumentsError - (hname header) targetType expected actual + if (actual == expected) + then return name + else + do + result <- asks $ methodLookup targetType defName + case result of + Just header' -> return defName + Nothing -> tcError $ WrongNumberOfMethodArgumentsError + (hname header) targetType expected actual where + name = hname header + defName = Name ("_" ++ show(name) ++ show (expected - actual)) actual = length args expected = length (hparams header) + meetRequiredFields :: [FieldDecl] -> Type -> TypecheckM () meetRequiredFields cFields trait = do tdecl <- findTrait trait @@ -695,15 +704,16 @@ instance Checkable Expr where (header, calledType) <- findMethodWithCalledType targetType (name mcall) - matchArgumentLength targetType header (args mcall) + calledName <- matchArgumentLength targetType header (args mcall) isActive <- isActiveType targetType let eTarget' = if isThisAccess eTarget && isActive && isMethodCall mcall then setType (makeLocal calledType) eTarget else setType calledType eTarget + typeParams = htypeparams header - argTypes = map ptype $ hparams header + argTypes = map ptype $ take (length (args mcall)) (hparams header) resultType = htype header (eArgs, resultType', typeArgs) <- @@ -726,7 +736,8 @@ instance Checkable Expr where return $ setArrowType (arrowType argTypes resultType) $ setType returnType' mcall {target = eTarget' ,args = eArgs - ,typeArguments = typeArgs} + ,typeArguments = typeArgs + ,name = calledName } errorInitMethod targetType name = do when (name == constructorName) $ tcError ConstructorCallError @@ -800,24 +811,34 @@ instance Checkable Expr where let typeParams = getTypeParameters ty argTypes = getArgTypes ty resultType = getResultType ty + actualLength = length args + expectedLength = length argTypes + defName = qname'{qnlocal = Name $ "_" ++ show qname ++ show (expectedLength - actualLength)} + + calledName <- + if (actualLength == expectedLength) + then return qname' + else do + result2 <- findVar defName + case result2 of + Just (qname2, ty2) -> return defName + Nothing -> tcError $ WrongNumberOfFunctionArgumentsError + qname (length argTypes) (length args) unless (isArrowType ty) $ tcError $ NonFunctionTypeError ty - unless (length args == length argTypes) $ - tcError $ WrongNumberOfFunctionArgumentsError - qname (length argTypes) (length args) (eArgs, returnType, typeArgs) <- if null typeArguments - then inferenceCall fcall typeParams argTypes resultType + then inferenceCall fcall typeParams (take actualLength argTypes) resultType else do unless (length typeArguments == length typeParams) $ tcError $ WrongNumberOfFunctionTypeArgumentsError qname (length typeParams) (length typeArguments) - typecheckCall fcall typeParams argTypes resultType + typecheckCall fcall typeParams (take actualLength argTypes) resultType return $ setArrowType ty $ setType returnType fcall {args = eArgs, - qname = qname', + qname = calledName, typeArguments = typeArgs} --- |- t1 .. |- tn From 72686779841feb6ab6b26f4f7d13d9d10903dbe6 Mon Sep 17 00:00:00 2001 From: EliasC Date: Thu, 1 Jun 2017 16:42:43 +0200 Subject: [PATCH 18/18] Add implicit constructor call in main class This commit adds an implicit call to `init` at the beginning of the `main` method. It also adds a restriction from defining a constructor method in the `Main` class. "Why this madness?" I hear you ask. This is to give field initialization a place to be desugared into, while still keeping `main` as the starting point of the program. --- src/opt/Optimizer/Optimizer.hs | 22 +++++++++++++++++++-- src/tests/encore/basic/mainConstructor.enc | 8 ++++++++ src/tests/encore/basic/mainConstructor.fail | 1 + src/types/Typechecker/Prechecker.hs | 5 +++++ src/types/Typechecker/TypeError.hs | 3 +++ 5 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 src/tests/encore/basic/mainConstructor.enc create mode 100644 src/tests/encore/basic/mainConstructor.fail diff --git a/src/opt/Optimizer/Optimizer.hs b/src/opt/Optimizer/Optimizer.hs index 2b9fe71e6..3fc3f3e87 100644 --- a/src/opt/Optimizer/Optimizer.hs +++ b/src/opt/Optimizer/Optimizer.hs @@ -19,8 +19,26 @@ optimizeProgram p@(Program{classes, traits, functions}) = optimizeTrait t@(Trait{tmethods}) = t{tmethods = map optimizeMethod tmethods} - optimizeClass c@(Class{cmethods}) = - c{cmethods = map optimizeMethod cmethods} + optimizeClass c@(Class{cname, cmethods}) + | isMainClass c = + c{cmethods = map (optimizeMethod . addMainInitCall) cmethods} + | otherwise = + c{cmethods = map optimizeMethod cmethods} + where + addMainInitCall m@Method{mbody} + | isMainMethod cname (methodName m) = + let em = emeta mbody + this = setType cname + VarAccess{emeta = em, qname = qLocal thisName} + initCall = setType unitType + MethodCall{emeta = em + ,target = this + ,name = constructorName + ,typeArguments = [] + ,args = [] + } + in m{mbody = Seq{emeta = emeta mbody, eseq = [initCall, mbody]}} + | otherwise = m optimizeMethod m = m{mbody = optimizeExpr (mbody m)} diff --git a/src/tests/encore/basic/mainConstructor.enc b/src/tests/encore/basic/mainConstructor.enc new file mode 100644 index 000000000..4b0699262 --- /dev/null +++ b/src/tests/encore/basic/mainConstructor.enc @@ -0,0 +1,8 @@ +active class Main + def init() : unit + () + end + def main(args : [String]) : unit + () + end +end diff --git a/src/tests/encore/basic/mainConstructor.fail b/src/tests/encore/basic/mainConstructor.fail new file mode 100644 index 000000000..14936adeb --- /dev/null +++ b/src/tests/encore/basic/mainConstructor.fail @@ -0,0 +1 @@ +Main class cannot have a constructor diff --git a/src/types/Typechecker/Prechecker.hs b/src/types/Typechecker/Prechecker.hs index d814e25d9..68f7ab2f1 100644 --- a/src/types/Typechecker/Prechecker.hs +++ b/src/types/Typechecker/Prechecker.hs @@ -335,6 +335,11 @@ instance Precheckable MethodDecl where Just (_, thisType) <- findVar (qLocal thisName) when (isMainMethod thisType (methodName m)) (checkMainParams $ hparams mheader') + + when (isMainType thisType && isConstructor m) $ + unless (isImplicitMethod m) $ + tcError MainConstructorError + when (isStreamMethod m) $ do unless (isActiveSingleType thisType) $ tcError PassiveStreamingMethodError diff --git a/src/types/Typechecker/TypeError.hs b/src/types/Typechecker/TypeError.hs index a691bcba7..9e52e424b 100644 --- a/src/types/Typechecker/TypeError.hs +++ b/src/types/Typechecker/TypeError.hs @@ -219,6 +219,7 @@ data Error = | PolymorphicConstructorError | StreamingConstructorError | MainMethodArgumentsError + | MainConstructorError | FieldNotFoundError Name Type | MethodNotFoundError Name Type | BreakOutsideOfLoopError @@ -468,6 +469,8 @@ instance Show Error where "Constructor cannot be streaming" show MainMethodArgumentsError = "Main method must have argument type () or ([String])" + show MainConstructorError = + "Main class cannot have a constructor" show (FieldNotFoundError name ty) = printf "No field '%s' in %s" (show name) (refTypeName ty)