Commit ecd561ca authored by Camil Staps's avatar Camil Staps 🚀

Several checks on Builtin.Syntax in CI

parent 6a5b5f37
Pipeline #18102 passed with stages
in 18 minutes and 45 seconds
......@@ -16,3 +16,5 @@ typetree.dot
cloogle.log
db/storage/
cache
test/builtin_syntax
variables:
GIT_SUBMODULE_STRATEGY: recursive
stages:
- check
- build
style syntax documentation:
stage: check
image: camilstaps/clean:nightly
only:
changes:
- backend/Builtin/Syntax.icl
script:
- cd backend
- ./install_clean.sh
- cd ../test
- make test
backend:
stage: build
image: camilstaps/clean:nightly
script:
- cd backend
......@@ -13,12 +30,14 @@ backend:
- backend/typetree.dot
frontend:
stage: build
image: php:apache
script:
- cd frontend
- ./build.sh
stats:
stage: build
image: debian:stretch
script:
- cd stats
......
implementation module Builtin.Syntax
import StdArray
import StdFunctions
import StdList
import StdString
......@@ -73,9 +74,18 @@ builtin_syntax =
]
EX :: !String -> SyntaxExample
EX c = {example=c, cleanjs_start=Nothing}
EX c = {example=c, cleanjs_start=Nothing, bootstrap=[], requires_itask_compiler=False}
EXs :: !String !String -> SyntaxExample
EXs s c = {example=c, cleanjs_start=Just s}
EXs s c = {EX c & cleanjs_start=Just s}
add_imports :: ![String] !SyntaxExample -> SyntaxExample
add_imports is se = {se & bootstrap=["import " +++ mod \\ mod <- is] ++ se.bootstrap}
add_bootstrap :: !String !SyntaxExample -> SyntaxExample
add_bootstrap bs se = {se & bootstrap=se.bootstrap ++ [bs]}
requires_itask_compiler :: !SyntaxExample -> SyntaxExample
requires_itask_compiler se = {se & requires_itask_compiler=True}
bs_basicvalues =
{ syntax_title = "basic values"
......@@ -111,7 +121,8 @@ bs_case =
]
, syntax_doc_locations = [CLR 5 "3.4.2" "_Toc311798001"]
, syntax_examples =
[ EXs "macro" "isJust m = case m of\n\tJust _ -> True\n\t_ -> False"
[ add_imports ["StdMaybe"] $ EXs "macro"
"isJust m = case m of\n\tJust _ -> True\n\t_ -> False"
]
}
......@@ -128,7 +139,7 @@ bs_class =
, syntax_doc_locations = [CLR 8 "6.1" "_Toc311798056"]
, syntax_examples = map EX
[ "class zero a :: a // one member"
, "class Text s // multiple members\nwhere\n\ttextSize :: !s -> Int\n\tconcat :: ![s] -> s\n\t// ..."
, "class Text s // multiple members\nwhere\n\ttextSize :: !s -> Int\n\tconcat :: ![s] -> s\n\t/* etc... */"
]
}
......@@ -172,12 +183,14 @@ bs_context =
, "The generic context is written without kinds and separated by `,` as seen in the example."
]
, syntax_doc_locations = [CLR 8 "6.2" "_Toc311798057"]
, syntax_examples = map EX
[ "add :: a a -> a | + a // a must instantiate +\nadd x y = x + y"
, "sum :: [a] -> a | zero, + a // a must instantiate zero and +\nsum [] = zero\nsum [x:xs] = x + sum xs"
, "(<+) infixr 5 :: a b -> String | toString a & toString b // a and b must instantiate toString\n(<+) x y = toString x +++ toString y"
, "isMember :: a [a] -> Bool special a=Int // specialised instance for integer lists for efficiency"
, "generic gFun a | gDefault a, gEq a :: a -> Int // generic context"
, syntax_examples = map (add_imports ["StdEnv","Data.GenEq"] o EX)
[ "add :: a a -> a | + a // a must instantiate +\nadd x y = x + y"
, "sum :: [a] -> a | zero, + a // a must instantiate zero and +\nsum [] = zero\nsum [x:xs] = x + sum xs"
, "(<+) infixr 5 :: a b -> String\n" +
"\t| toString a & toString b // a and b must instantiate toString\n" +
"(<+) x y = toString x +++ toString y"
, "contains :: a [a] -> Bool special a=Int // specialised instance for integer lists for efficiency"
, "generic gFun a | gEq a :: a -> Int // generic context"
]
}
......@@ -190,7 +203,7 @@ bs_define_constant =
"This is the default understanding of `=` in local scope.\n\n" +
"The inverse is {{`=>`}}, which defines an identifier to be a constant function."
, syntax_doc_locations = [CLR 5 "3.6" "_Toc311798007"]
, syntax_examples = [EXs "macro" "mylist =: [1..10000]"]
, syntax_examples = [add_imports ["StdEnum"] $ EXs "macro" "mylist =: [1..10000]"]
}
bs_define_graph =
{ syntax_title = "constant function definition"
......@@ -201,7 +214,7 @@ bs_define_graph =
"This is the default understanding of `=` in global scope.\n\n" +
"The inverse is {{`=:`}}, which defines an identifier to be a graph."
, syntax_doc_locations = [CLR 5 "3.6" "_Toc311798007"]
, syntax_examples = [EXs "macro" "mylist => [1..10000]"]
, syntax_examples = [add_imports ["StdEnum"] $ EXs "macro" "mylist => [1..10000]"]
}
bs_dotdot =
......@@ -212,7 +225,7 @@ bs_dotdot =
"A shorthand for lists of enumerable types.\n\n" +
"To use these expressions, you must import {{`StdEnum`}}. The underlying functions are defined in {{`_SystemEnum`}}."
, syntax_doc_locations = [CLR 6 "4.2.1" "_Toc311798023"]
, syntax_examples = map (EXs "macro")
, syntax_examples = map (add_imports ["StdEnum"] o EXs "macro")
[ "xs = [0..] // 0, 1, 2, 3, ..."
, "xs = [0,2..] // 0, 2, 4, 6, ..."
, "xs = [0..10] // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10"
......@@ -240,10 +253,13 @@ bs_extensible_adt =
, "It is not possible to derive generic functions for EADTs."
]
, syntax_doc_locations = []
, syntax_examples = map EX
[ ":: T = .. // Declare T as an EADT"
, ":: T = C1 | .. // Declare T to be an EADT with at least the constructor C1"
, ":: T | C // Extend the EADT T with constructor C"
, syntax_examples =
[ EX
":: T = .. // Declare T as an EADT"
, EX
":: T = C1 | .. // Declare T to be an EADT with at least the constructor C1"
, add_bootstrap ":: T = .." $ EX
":: T | C // Extend the EADT T with constructor C"
]
}
......@@ -253,10 +269,10 @@ bs_forall =
, syntax_code = ["A. ...:"]
, syntax_description = "Explicitly marks polymorphic type variables. Clean does not yet allow universal quantifiers on the topmost level."
, syntax_doc_locations = [CLR 5 "3.7.4" "_Toc311798013"]
, syntax_examples = map EX
[ "hd :: A.a: [a] -> a // Not yet allowed: A. on the topmost level"
, "h :: (A.a: [a] -> Int) -> Int // The quantifier is needed to apply the function to both a [Int] and a [Char]\nh f = f [1..100] + f ['a'..'z']"
, syntax_examples = map (add_imports ["StdEnv"] o EX)
[ "h :: (A.a: [a] -> Int) -> Int // The quantifier is needed to apply the function to both a [Int] and a [Char]\nh f = f [1..100] + f ['a'..'z']"
, ":: T = C (A.a: a -> a) // In a type"
, "hd :: A.a: [a] -> a // Not allowed: A. on the topmost level"
]
}
......@@ -286,13 +302,10 @@ bs_funcdep =
"Lets you point the type checker to the type that determines the other types.\n\n" +
"Most often this is the return type (undocumented and experimental)."
, syntax_doc_locations = []
, syntax_examples = map EX
[ "class plus a b c :: a b -> c\n" +
"instance plus Int Int Int where plus x y = x + y\n" +
"Start = plus 1 (plus 1 1) // Results in: internal overloading of \"plus\" could not be solved because the compiler doesn't know the type of the intermediate result."
, "class plus a b ~c :: a b -> c\n" +
, syntax_examples = map (requires_itask_compiler o EX)
[ "class plus a b ~c :: a b -> c\n" +
"instance plus Int Int Int where plus x y = x + y\n" +
"Start = plus 1 (plus 1 1) // Works! because we told the compiler that c determines the other types."
"Start = plus 1 (plus 1 1) // Overloading can be resolved because we told the compiler that c determines the other types."
]
}
......@@ -324,7 +337,7 @@ bs_guard =
, "However, one must be consistent with this throughout the function."
]
, syntax_doc_locations = [CLR 5 "3.3" "_Toc311797998"]
, syntax_examples = map EX
, syntax_examples = map (add_imports ["StdEnv"] o EX)
[ "sign :: !Int -> Int\nsign n\n| n < 0 = -1 // Negative number\n| n == 0 = 0 // Zero\n| otherwise = 1 // Must be positive"
]
}
......@@ -339,17 +352,23 @@ bs_generic =
, "Generic functions are said to be kind-indexed, i.e., a generic is actually a group of functions with different types depending on the kind of the deriving type."
]
, syntax_doc_locations = [CLR 9 "7.2" "_Toc311798069"]
, syntax_examples = map EX
[ "generic gEq a :: !a !a -> Bool // The type of a generic function"
, "gEq{|Int|} x y = x == y // Implementation of a generic\n" +
, syntax_examples =
[ add_imports ["StdEnv","StdGeneric"] $ EX $
"generic gEq a :: !a !a -> Bool // The type of a generic function\n" +
"gEq{|Int|} x y = x == y // Implementation of a generic\n" +
"gEq{|PAIR|} fx fy (PAIR x1 y1) (PAIR x2 y2) = fx x1 x2 && fy y1 y2"
, "derive gEq [] // Deriving the gEq generic for type []"
, "gConsName{|CONS of d|} _ = d.gcd_name // Using type information"
, "gFun{|CONS of {gcd_arity}|} // Using a specific field of type information, the compiler will only provide this field which makes it a lot faster"
, "generic gFun a :: a -> Int | gDefault a // A generic function with a generic context. The context will become an argument.\n" +
"derive gFun CONS of {gcd_arity} with f _ // A derivation that does not use all arguments. The compiler can optimize even more.\n" +
"gFun{|CONS of {gcd_arity}|} f _ = // A derivation that does not use the context and only one field of the generic type descriptor, the compiler can optimize for this."
, "generic gShared a *! :: ... // A generic function that will use a bimap without uniqueness attributes (very experimental, see https://gitlab.science.ru.nl/clean-and-itasks/clean-language-report/blob/master/experimental/binumap.md).\n"
, add_imports ["StdMaybe", "Data.GenEq"] $ EX
"derive gEq Maybe // Deriving the gEq generic for type Maybe"
, add_imports ["StdGeneric"] $ add_bootstrap "generic gConsName a :: a -> String" $ EX
"gConsName{|CONS of d|} _ _ = d.gcd_name // Using type information"
, add_imports ["StdGeneric"] $ add_bootstrap "generic gConsName a :: a -> String" $ EX
"gConsName{|CONS of {gcd_name}|} _ _ = gcd_name // Using a specific field of type information, the compiler can optimise the function"
, add_imports ["StdGeneric", "StdMisc", "Data.GenDefault"] $ EX $
"generic gFun a | gDefault a :: a -> Int // A generic function with a generic context. The context will become an argument.\n" +
"derive gFun CONS of {gcd_arity} with f _ // A derivation that does not use all arguments. The compiler can optimize even more.\n" +
"gFun{|CONS of {gcd_arity}|} f _ _ = undef // A derivation that does not use the context and only one field of the generic type descriptor, the compiler can optimize for this."
, requires_itask_compiler $ EX $
"generic gShared a *! :: a // A generic function using a bimap without uniqueness attributes (only supported by the iTask compiler; see https://gitlab.science.ru.nl/clean-and-itasks/clean-language-report/blob/master/experimental/binumap.md)\n"
]
}
......@@ -381,11 +400,12 @@ bs_import =
[ "import StdEnv // Import all code from the StdEnv definition module"
, "from StdFunc import o // Import only the o function from StdFunc"
, "import qualified Data.Map // Import Data.Map such that functions are available as e.g. 'Data.Map'.get."
, "import qualified Data.Map as M // Import Data.Map such that functions are available as e.g. 'M'.get."
, "import Control.Monad => qualified join // Import all code from Control.Monad except for join. join is imported qualified"
, "import code from \"tty.\" // Import functions from the object file matching 'Clean System Files/tty.*'"
, "import code from library \"msvcrt\" // Import functions from linked DLLs according to the msvcrt file in Clean System Files.\n" +
" // The file should start with the DLL name (e.g. msvcrt) and followed by one line per function you want to link."
] ++ map (requires_itask_compiler o EX)
[ "import qualified Data.Map as M // Import Data.Map to use as e.g. 'M'.get (only supported by the iTask compiler)"
, "import Control.Monad => qualified join // Import Control.Monad except for join; join is imported qualified (only supported by the iTask compiler)"
]
}
......@@ -411,7 +431,7 @@ bs_instance =
, syntax_code = ["instance ... ... where ..."]
, syntax_description = "Defines an instantiation of a {{class}} for a type."
, syntax_doc_locations = [CLR 8 "6.1" "_Toc311798056"]
, syntax_examples = map EX
, syntax_examples = map (add_imports ["StdOverloaded"] o EX)
[ "instance zero Int\nwhere\n\tzero = 0"
, "instance zero Real\nwhere\n\tzero = 0.0"
]
......@@ -423,7 +443,7 @@ bs_lambda =
, syntax_code = ["\\... -> ...", "\\... . ...", "\\... = ..."]
, syntax_description = "An anonymous, inline function."
, syntax_doc_locations = [CLR 5 "3.4.1" "_Toc311798000"]
, syntax_examples = map (EXs "macro")
, syntax_examples = map (add_imports ["StdList"] o EXs "macro")
[ "(o) f g = \\x -> f (g x) // Simple lambda expression"
, "swapall = map (\\(x,y) -> (y,x)) // Pattern matching in lambda arguments"
, "mul = \\x y -> x * y // Multiple arguments (of course, it would be better to write `mul x y = x * y` or `mul = (*)`)"
......@@ -458,8 +478,15 @@ bs_let =
, syntax_description = "An expression that introduces new scope."
, syntax_doc_locations = [CLR 5 "3.5.1" "_Toc311798003"]
, syntax_examples =
[ EXs "macro" "fac n = let fs = [1:1:[(fs!!(i-1)) + (fs!!(i-2)) \\ i <- [2..]]] in fs !! n"
, EXs "macrorhs" "let // Multi-line let expressions\n\tfunction args = body\n\tselector = expr\n\t// ...\nin expression"
[ add_imports ["StdEnv"] $
EXs "macro"
"fac n = let fs = [1:1:[(fs!!(i-1)) + (fs!!(i-2)) \\\\ i <- [2..]]] in fs !! n"
, add_imports ["StdMisc"] $
add_bootstrap "body = undef" $
add_bootstrap "expr = undef" $
add_bootstrap "expression = undef" $
EXs "macrorhs"
"let // Multi-line let expressions\n\tfunction args = body\n\tselector = expr\n\t// ...\nin expression"
]
}
bs_let_before =
......@@ -469,7 +496,13 @@ bs_let_before =
, syntax_description = "A {{`let`}} expression that can be defined before a guard or function body, which eases the syntax of sequential actions."
, syntax_doc_locations = [CLR 5 "3.5.4" "_Toc311798006"]
, syntax_examples =
[ EX "readchars :: *File -> *([Char], *File)\nreadchars f\n# (ok,c,f) = freadc file\n| not ok = ([], f)\n# (cs,f) = readchars f\n= ([c:cs], f)"
[ add_imports ["StdEnv"] $ EX $
"readchars :: *File -> *([Char], *File)\n" +
"readchars f\n" +
"# (ok,c,f) = freadc f\n" +
"| not ok = ([], f)\n" +
"# (cs,f) = readchars f\n" +
"= ([c:cs], f)"
]
}
......@@ -484,9 +517,9 @@ bs_list_expressions =
, syntax_doc_locations = [CLR 6 "4.2.1" "_Toc311798021"]
, syntax_examples = map (EXs "macro")
[ "abc = ['a', 'b', 'c'] // Individual elements"
, "abc = ['a':['b':['c':[]]] // Head and tail, ending with the empty list"
, "abc = ['abc'] // Special syntax for [Char] lists"
, "abc ['abc':rest] = True // The special syntax can als be used to patternmatch"
, "abc = ['a':['b':['c':[]]]] // Head and tail, ending with the empty list"
, "abc = ['abc'] // Syntax shorthand for [Char] lists"
, "abc ['abc':rest] = True // The shorthand can als be used to patternmatch"
]
}
......@@ -520,7 +553,7 @@ bs_module =
}
bs_newtype =
{ syntax_title = "Newtype definition (experimental)"
{ syntax_title = "newtype definition"
, syntax_patterns = map exact ["=:", "newtype"]
, syntax_code = [":: ... =: ... ..."]
, syntax_description = "A newtype is a type synonym at run-time but treated as a real type at compile-time.\n"
......@@ -533,12 +566,18 @@ bs_newtype =
}
bs_overloaded_type_variable =
{ syntax_title = "Overloaded type variable"
{ syntax_title = "overloaded type variable"
, syntax_patterns = map exact ["\\^", "\\w\\^"]
, syntax_code = ["... :: ...^"]
, syntax_description = "A pattern match on the type of a dynamic depending on the type of the function."
, syntax_doc_locations = [CLR 10 "8.2.5" "_Toc311798087"]
, syntax_examples = [EX "unpack :: Dynamic -> Maybe a\nunpack (x :: a^) = Just x // Only values of type a\nunpack _ = Nothing"]
, syntax_examples =
[ add_imports ["StdMaybe"] $
EX $
"unpack :: Dynamic -> Maybe a | TC a\n" +
"unpack (x :: a^) = Just x // Only values of type a\n" +
"unpack _ = Nothing"
]
}
bs_pattern_named =
......@@ -547,7 +586,7 @@ bs_pattern_named =
, syntax_code = ["...=:(...)"]
, syntax_description = "Give a name to the expression of a pattern to be able to use the whole expression without creating new graphs."
, syntax_doc_locations = [CLR 5 "3.2" "_Toc311797997"]
, syntax_examples = map EX
, syntax_examples = map (add_imports ["StdMaybe"] o EX)
[ "isJustU e=:(Just _) = (True, e) // On an ADT"
, ":: Position = {px :: Int, py :: Int}\ngetx p=:{px} = (px, p) // On a record; this has type :: Position -> (Int, Position)"
]
......@@ -574,9 +613,11 @@ bs_qualified_identifier =
, syntax_code = ["'...'. ..."]
, syntax_description = "The identifiers of {{`qualified`}} imports must be prepended with `'...'.`, where `...` is the name of the qualified import."
, syntax_doc_locations = []
, syntax_examples = map EX
[ "import qualified StdList\nStart = 'StdList'.sum [0..10]"
, "import qualified StdList as L\nStart = 'L'.sum [0..10]"
, syntax_examples =
[ add_imports ["StdEnum"] $ EX
"import qualified StdList\nStart = 'StdList'.sum [0..10]"
, add_imports ["StdEnum"] $ requires_itask_compiler $ EX
"import qualified StdList as L // requires the iTask compiler\nStart = 'L'.sum [0..10]"
]
}
......@@ -599,9 +640,9 @@ bs_selection_array =
, syntax_code = [".[i]", ".[i,j,...]"]
, syntax_description = "Select an element from a (possibly multidimensional) array. The indexes must have the type {{`Int`}}."
, syntax_doc_locations = [CLR 6 "4.4.1" "_Toc311798033"]
, syntax_examples = map (EXs "macro")
[ "five = {1,2,3,4,5,6,7,8,9,10}.[4] // Arrays are zero-indexed"
, "five = {{1,2},{3,4,5},{6,7,8}}.[1,2] // This is equivalent to (...).[1].[2]"
, syntax_examples = map (add_imports ["StdEnv"] o EXs "macro")
[ "five = {!1,2,3,4,5,6,7,8,9,10}.[4] // Arrays are zero-indexed"
, "five = {!{!1,2},{3,4,5},{6,7,8}}.[1,2] // This is equivalent to (...).[1].[2]"
]
}
bs_selection_array_unique =
......@@ -610,9 +651,9 @@ bs_selection_array_unique =
, syntax_code = ["![i]", "![i,j,...]"]
, syntax_description = "Select an element from a (possibly multidimensional, possibly unique) array and return both the element and the array. The indexes must have the type {{`Int`}}."
, syntax_doc_locations = [CLR 6 "4.4.1" "_Toc311798033"]
, syntax_examples = map (EXs "macro")
[ "(five,arr) = {1,2,3,4,5,6,7,8,9,10}![4]"
, "(five,arr) = {{1,2},{3,4,5},{6,7,8}}![1,2]"
, syntax_examples = map (add_imports ["StdEnv"] o EXs "macro")
[ "(five,arr) = {!1,2,3,4,5,6,7,8,9,10}![4]"
, "(five,arr) = {!{!1,2},{3,4,5},{6,7,8}}![1,2]"
]
}
bs_selection_record =
......@@ -621,7 +662,11 @@ bs_selection_record =
, syntax_code = ["."]
, syntax_description = "Select a field from a (possibly multilevel) record."
, syntax_doc_locations = [CLR 7 "5.2.1" "_Toc311798050"]
, syntax_examples = map (EXs "macro")
, syntax_examples = map
( add_bootstrap ":: Position = {px :: Int, py :: Int}"
o add_bootstrap ":: Position3D = {pxy :: Position, pz :: Int}"
o EXs "macro"
)
[ "five = {px=5, py=10}.px"
, "five = {pxy={px=5, py=10}, pz=2}.pxy.px"
, "five = {px=5, py=10}.Position.px // If multiple records have a field px, the type name can be used for disambiguation"
......@@ -633,7 +678,11 @@ bs_selection_record_unique =
, syntax_code = ["!"]
, syntax_description = "Select a field from a (possibly multilevel, possibly unique) record and return both the field data and the record."
, syntax_doc_locations = [CLR 7 "5.2.1" "_Toc311798050"]
, syntax_examples = map (EXs "macro")
, syntax_examples = map
( add_bootstrap ":: Position = {px :: Int, py :: Int}"
o add_bootstrap ":: Position3D = {pxy :: Position, pz :: Int}"
o EXs "macro"
)
[ "(five,rec) = {px=5, py=10}!px"
, "(five,rec) = {pxy={px=5, py=10}, pz=2}!pxy.px // Only the first field should have the exclamation mark"
, "(five,rec) = {px=5, py=10}!Position.px // If multiple records have a field px, the type name can be used for disambiguation\n" +
......@@ -710,7 +759,7 @@ bs_unique =
, "`T = T (Int *Int -> *Int)` has to be `T = T (Int -> *(*Int -> *Int))`."
]
, syntax_doc_locations = [CLR 11 "9.1" "_Toc311798093"]
, syntax_examples = map EX
, syntax_examples = map (add_imports ["StdEnv"] o EX)
[ "Start :: *World -> *World // World is unique"
, "copyArray :: *(a e) -> *(*a e, *a e) | Array a e // Add parentheses when needed"
, "f :: .a -> .a // f works on unique and non-unique values"
......@@ -757,7 +806,13 @@ bs_where_instance =
, syntax_code = ["where"]
, syntax_description = "Introduces the implementation of an {{`instance`}}."
, syntax_doc_locations = [CLR 8 "6.1" "_Toc311798056"]
, syntax_examples = [EX "instance Arith Int // Instance definition\nwhere\n\t(+) x y = // ...\n\t(-) x y = // ..."]
, syntax_examples =
[ add_imports ["StdEnv"] $ EX $
":: T = C Int\n" +
"instance + T\n" +
"where\n" +
"\t(+) (C x) (C y) = C (x+y)"
]
}
bs_where_local =
{ syntax_title = "where"
......@@ -765,7 +820,13 @@ bs_where_local =
, syntax_code = ["where"]
, syntax_description = "Introduces local definitions. For guard-local definitions, see {{`with`}}."
, syntax_doc_locations = [CLR 5 "3.5.2" "_Toc311798004"]
, syntax_examples = [EXs "macro" "primes = sieve [2..] // Local definitions\nwhere\n\tsieve [pr:r] = [pr:sieve (filter pr r)]"]
, syntax_examples =
[ add_imports ["StdEnv"] $
EXs "macro" $
"primes = sieve [2..] // Local definitions\n" +
"where\n" +
"\tsieve [pr:r] = [pr:sieve (filter (\\n -> n rem pr <> 0) r)]"
]
}
bs_with =
......@@ -774,7 +835,16 @@ bs_with =
, syntax_code = ["with"]
, syntax_description = "Introduces guard-local definitions. For function-local definitions, see {{`where`}}."
, syntax_doc_locations = [CLR 5 "3.5.3" "_Toc311798005"]
, syntax_examples = [EXs "macro" "f x y\n| guard1 = alt1\n\twith local = expr1\n| guard2 = alt2\n\twith local = expr2"]
, syntax_examples =
[ add_imports ["StdEnv"] $
EXs "macro" $
"f g x y\n" +
"| x < 0 = g local\n" +
"\twith local = x + y\n" +
"| x > 0 = g local\n" +
"\twith local = x - y\n" +
"| otherwise = g 0"
]
}
bs_zf =
......@@ -786,7 +856,7 @@ bs_zf =
]
, syntax_description = "Constructs a list or array composed of elements drawn from other lists or arrays."
, syntax_doc_locations = [CLR 6 "4.2.1" "_Toc311798024", CLR 6 "4.4.1" "_Toc311798032"]
, syntax_examples = map (EXs "macro")
, syntax_examples = map (add_imports ["StdEnv", "StdMaybe"] o EXs "macro")
[ "cartesian = [(x,y) \\\\ x <- [1,2,3], y <- [10,20]] // Cartesian product: (1,10), (1,20), (2,10), (2,20), (3,10), (3,20)"
, "zip xs ys = [(x,y) \\\\ x <- xs & y <- ys] // Pairwise zip through the lists"
, "filter f xs = [x \\\\ x <- xs | f x] // Guard to add conditions"
......
Subproject commit 13dae5a9925385784d5dfd1a38d92cdfa6b7dc05
Subproject commit 6297f08b2b5dbd66face8a15f9df24c3a8d670b1
#!/bin/bash
set -ev
PATCHCLEANBUILD="sed -i 's:clean-compiler-and-rts compiler itask:cstaps compiler master:' clean-base/linux-x64/git-sources.txt; sed -i 's:compiler-itask:compiler-master:' clean-base/linux-x64/build.sh; sed -i 's:master:cloogle:' clean-lib-platform/linux-x64/git-sources.txt; sed -i 's:platform-master:platform-cloogle:' clean-lib-platform/linux-x64/build.sh" install_clean.sh 'base lib-platform lib-tcpip' 2018-12-28
./install_clean.sh
sed -i 's/cocl/cocl::-wmf/' /opt/clean/etc/IDEEnvs
PACKAGES="patch jq unzip z3"
......
#!/bin/bash
set -ev
PATCHCLEANBUILD="sed -i 's:clean-compiler-and-rts compiler itask:cstaps compiler master:' clean-base/linux-x64/git-sources.txt; sed -i 's:compiler-itask:compiler-master:' clean-base/linux-x64/build.sh; sed -i 's:master:cloogle:' clean-lib-platform/linux-x64/git-sources.txt; sed -i 's:platform-master:platform-cloogle:' clean-lib-platform/linux-x64/build.sh" install_clean.sh 'base lib-dynamics lib-platform lib-tcpip' 2019-01-27
CLM:=clm
CLMFLAGS:=-nr -nt\
-I ../backend\
-I ../backend/Cloogle\
-I ../backend/Cloogle/libcloogle\
-I ../backend/Cloogle/CleanRegex\
-IL Platform
BIN:=builtin_syntax
TEST:=$(addprefix test_,$(BIN))
test: $(TEST)
$(TEST): test_%: %
./$<
$(BIN): .FORCE
$(CLM) $(CLMFLAGS) $@ -o $@
.FORCE:
.PHONY: test .FORCE
module builtin_syntax
import StdEnv
import StdMaybe
import Clean.Types
import Clean.Types.Parse
from Data.Func import mapSt, seqSt
import Data.List
import System.CommandLine
import System.Directory
import System.File
import System.FilePath
import System.Process
import Text
from Cloogle.API import :: SyntaxExample{..}
import Cloogle.DB
import Builtin.Syntax
DOT_SUCCESS :== "\033[0;32m.\033[0m"
DOT_FAILURE :== "\033[0;31mF\033[0m"
DOT_SKIPPED :== "\033[0;33ms\033[0m"
MSG_SUCCESS :== "\033[0;32m OK\033[0m"
MSG_FAILURE :== "\033[0;31m failed!\033[0m"
DIRECTORY :== "examples"
CLMFLAGS =:
[ "-c"
, "-dynamics"
, "-IL", "Dynamics"
, "-IL", "Platform"
]
Start w
# (_,w) = ensureDirectoryExists DIRECTORY w
# (_,failed,w) = seqSt test builtin_syntax (0,0,w)
= case failed of
0
# (_,w) = recursiveDelete DIRECTORY w
-> w
_
# (_,w) = fclose
(stderr
<<< "Some tests failed. If test numbers are given, you can check the errors with:\n"
<<< "\tcd " <<< DIRECTORY <<< "\n"
<<< "\tclm " <<< join " " CLMFLAGS <<< " _example<number>\n")
w
-> setReturnCode -1 w
test :: !SyntaxEntry !*(!Int, !Int, !*World) -> *(!Int, !Int, !*World)
test se (i,failed,w)
# (comments_ok,i,w) = check_style se (i,w)
# failed = failed + if comments_ok 0 1
# err = stderr <<< "Checking syntax for '" <<< se.syntax_title <<< "': "
# (_,w) = fclose err w
# (results,(j,w)) = mapSt test_example se.syntax_examples (i,w)
# err = stderr
<<< if (and results)
MSG_SUCCESS
(MSG_FAILURE +++ " (" +++ join ", " [toString (n+i) \\ n <- [0..] & False <- results] +++ ")")
<<< "\n"
# (_,w) = fclose err w
= (j,failed + length [f \\ f=:False <- results],w)
check_style :: !SyntaxEntry !*(!Int, !*World) -> *(!Bool, !Int, !*World)
check_style se (i,w)
# err = stderr
# err = if comment_alignment_ok
err
(err
<<< "\033[0;31mComment alignment is inconsistent for '"
<<< se.syntax_title
<<< "' (at most two different levels may be used):\033[0m\n\t"
<<< join "\n\t" example_lines
<<< "\n")
# err = case no_spaces_around_comments of
[] -> err
ns -> err
<<< "\033[0;31mThese lines in '"
<<< se.syntax_title
<<< "' contain comments without spaces around the '//':\033[0m\n\t"
<<< join "\n\t" ns
<<< "\n"
# err = case missing_spaces of
[] -> err
ns -> err
<<< "\033[0;31mThese lines in '"
<<< se.syntax_title
<<< "' contain list comprehension elements without spaces around them:\033[0m\n\t"
<<< join "\n\t" ns
<<< "\n"
# (_,w) = fclose err w
= (True,i+1,w)
where
example_lines = concatMap (split "\n") [replaceSubString "\t" " " e.example \\ e <- se.syntax_examples]
comment_alignment_ok = length (removeDup comments) < 3
where
comments = filter ((<>) -1) [indexOf "//" l \\ l <- example_lines]
no_spaces_around_comments = filter bad example_lines
where
bad s = case indexOf "//" s of
-1 -> False
i -> s.[i-1] <> ' ' || s.[i+2] <> ' '
missing_spaces = filter bad example_lines
where
bad s
# s = replaceSubString "'\\\\'" "" s // special case for '\\' in basic_values
# (results,_) = mapSt check ["<|-","<-:","<-","\\\\"] s
= or results
check op s
# new = replaceSubString (" " +++ op +++ " ") "" s
= (indexOf op new >= 0, new)
test_example :: !SyntaxExample !*(!Int, !*World) -> *(!Bool, !*(!Int, !*World))
test_example {example,cleanjs_start,bootstrap,requires_itask_compiler} (i,w)
| requires_itask_compiler
|| indexOf "not allowed" (toLowerCase example) >= 0 // examples that are marked as not allowed by the compiler
|| startsWith "definition module " example // module headings
|| startsWith "implementation module " example
|| startsWith "system module " example
|| startsWith "module " example
# (_,w) = fclose (stderr <<< DOT_SKIPPED) w
= (True, (i+1,w))
# dcl = join "\n"
[ "definition module _example" <+ i
: [b \\ b <- bootstrap | startsWith "import " b]
++ case split "special" example of
[_]
| indexOf "(:==" example > 0
-> [example] // abstract synonym type
-> [l \\ l <- split "\n" example
| startsWith "derive " l && indexOf " with " l > 0
|| startsWith "generic " l]
[_:_]
-> [example]
]
# icl = join "\n"
[ "implementation module _example" <+ i
: bootstrap
++ case cleanjs_start of
Nothing -> complete_icl example
Just "macro" -> complete_icl example
Just "rhs" -> ["Start = " +++ example]
Just "macrorhs" -> ["Start = " +++ example]
Just s -> ["unknown cleanjs_start " +++ s]
]
# (_,w) = writeFile (DIRECTORY </> "_example" <+ i <+ ".dcl") dcl w
# (_,w) = writeFile (DIRECTORY </> "_example" <+ i <+ ".icl") icl w
# (Ok (h,_),w) = runProcessIO "clm" (CLMFLAGS ++ ["_example" <+ i]) (Just DIRECTORY) w
# (Ok r,w) = waitForProcess h w
# ok = r == 0
# (_,w) = fclose (stderr <<< if ok DOT_SUCCESS DOT_FAILURE) w
= (ok,(i+1,w))
where
complete_icl :: !String -> [String]
complete_icl example
| startsWith "foreign export " example =
[ name +++ " :: Int"
, name +++ " = 0"
] with name = example % (15, indexOfAfter 15 " " example)
| indexOf "(:==" example > 0 = // abstract synonym type
[replaceSubString "(:==" ":==" (example % (0,size example-2))]
# example = hd (split "special" example)
| example.[0] == '(' && indexOf ") =" example > 0 = // pattern
[ "tempfun = " +++ (example % (0,indexOf ") =" example + 1))
, "where"
, "\t" +++ replaceSubString "\n" "\n\t" example
]
# lines = split "\n" example
| length lines == 1
# line = hd lines
# line = case indexOf "//" line of
-1 -> line
i -> trim (line % (0, i-1))
# doublecolon = indexOf "::" line
| doublecolon > 0
&& not (startsWith "generic " line || startsWith "class " line)
// function without implementation
= case parseType [c \\ c <-: line & i <- [0..] | i > doublecolon+2] of
Just (Func is _ _) ->
[ line
, line % (0,indexOf " " line) +++ join " " ["_" \\ _ <- is] +++ " = undef"
, "from StdMisc import undef"
]
_ ->
[ line
, line % (0,indexOf " " line) +++ " = undef"
, "from StdMisc import undef"
]
= lines
= [l \\ l <- lines | not (startsWith "derive " l && indexOf " with " l > 0)]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment