lang: ast: The res and edge names should not use exclusives
This removes the exclusive from the res names and edge names. We now require that the names should be lists of strings, however they can still be single strings if that can be determined statically. Programmers should explicitly wrap their variables in a string by interpolation to force this, or in square brackets to force a list. The former is generally preferable because it generates a small function graph since it doesn't need to build a list.
This commit is contained in:
@@ -283,6 +283,14 @@ one of many ways you can perform iterative tasks that you might have
|
||||
traditionally used a `for` loop for instead. This is preferred, because flow
|
||||
control is error-prone and can make for less readable code.
|
||||
|
||||
The single `str` variation, may only be used when it is possible for the
|
||||
compiler to determine statically that the value is of that type. Otherwise, it
|
||||
will assume it to be a list of strings. Programmers should explicitly wrap their
|
||||
variables in a string by interpolation to force this static `str` determination,
|
||||
or in square brackets to force a list. The former is generally preferable
|
||||
because it generates a smaller function graph since it doesn't need to build a
|
||||
list.
|
||||
|
||||
##### Internal edges
|
||||
|
||||
Resources may also declare edges internally. The edges may point to or from
|
||||
@@ -337,6 +345,28 @@ to express a relationship between three resources. The first character in the
|
||||
resource kind must be capitalized so that the parser can't ascertain
|
||||
unambiguously that we are referring to a dependency relationship.
|
||||
|
||||
##### Edge naming
|
||||
|
||||
Each edge must have a unique name of type `str` that is used to uniquely
|
||||
identify that edge, and can be used in the functioning of the edge at its
|
||||
discretion.
|
||||
|
||||
Alternatively, the name value may be a list of strings `[]str` to build a list
|
||||
of edges, each with a name from that list.
|
||||
|
||||
Using this construct is a veiled form of looping (iteration). This technique is
|
||||
one of many ways you can perform iterative tasks that you might have
|
||||
traditionally used a `for` loop for instead. This is preferred, because flow
|
||||
control is error-prone and can make for less readable code.
|
||||
|
||||
The single `str` variation, may only be used when it is possible for the
|
||||
compiler to determine statically that the value is of that type. Otherwise, it
|
||||
will assume it to be a list of strings. Programmers should explicitly wrap their
|
||||
variables in a string by interpolation to force this static `str` determination,
|
||||
or in square brackets to force a list. The former is generally preferable
|
||||
because it generates a smaller function graph since it doesn't need to build a
|
||||
list.
|
||||
|
||||
#### Class
|
||||
|
||||
A class is a grouping structure that bind's a list of statements to a name in
|
||||
|
||||
@@ -326,6 +326,10 @@ func (obj *StmtBind) Output(map[interfaces.Func]types.Value) (*interfaces.Output
|
||||
// value can be a single string or a list of strings. The former will produce a
|
||||
// single resource, the latter produces a list of resources. Using this list
|
||||
// mechanism is a safe alternative to traditional flow control like `for` loops.
|
||||
// The `Name` value can only be a single string when it can be detected
|
||||
// statically. Otherwise, it is assumed that a list of strings should be
|
||||
// expected. More mechanisms to determine if the value is static may be added
|
||||
// over time.
|
||||
// TODO: Consider expanding Name to have this return a list of Res's in the
|
||||
// Output function if it is a map[name]struct{}, or even a map[[]name]struct{}.
|
||||
type StmtRes struct {
|
||||
@@ -576,39 +580,35 @@ func (obj *StmtRes) Unify() ([]interfaces.Invariant, error) {
|
||||
}
|
||||
invariants = append(invariants, invars...)
|
||||
|
||||
invarStr := &interfaces.EqualsInvariant{
|
||||
Expr: obj.Name,
|
||||
Type: types.TypeStr,
|
||||
}
|
||||
|
||||
// Optimization: If we know it's an str, no need for exclusives!
|
||||
// TODO: Check other cases, like if it's a function call, and we know it
|
||||
// can only return a single string. (Eg: fmt.printf for example.)
|
||||
isString := false
|
||||
if _, ok := obj.Name.(*ExprStr); ok {
|
||||
invariants = append(invariants, invarStr)
|
||||
// It's a string! (A plain string was specified.)
|
||||
isString = true
|
||||
}
|
||||
if typ, err := obj.Name.Type(); err == nil {
|
||||
// It has type of string! (Might be an interpolation specified.)
|
||||
if typ.Cmp(types.TypeStr) == nil {
|
||||
isString = true
|
||||
}
|
||||
}
|
||||
if isString {
|
||||
invar := &interfaces.EqualsInvariant{
|
||||
Expr: obj.Name,
|
||||
Type: types.TypeStr,
|
||||
}
|
||||
invariants = append(invariants, invar)
|
||||
|
||||
return invariants, nil
|
||||
}
|
||||
|
||||
invarListStr := &interfaces.EqualsInvariant{
|
||||
// Down here, we only allow []str, no need for exclusives!
|
||||
invar := &interfaces.EqualsInvariant{
|
||||
Expr: obj.Name,
|
||||
Type: types.TypeListStr,
|
||||
}
|
||||
|
||||
// Optimization: If we know it's a []str, no need for exclusives!
|
||||
if expr, ok := obj.Name.(*ExprList); ok {
|
||||
typ, err := expr.Type()
|
||||
if err == nil && typ.Cmp(types.TypeListStr) == nil {
|
||||
invariants = append(invariants, invarListStr)
|
||||
return invariants, nil
|
||||
}
|
||||
}
|
||||
|
||||
// name must be a string or a list
|
||||
ors := []interfaces.Invariant{}
|
||||
ors = append(ors, invarStr)
|
||||
ors = append(ors, invarListStr)
|
||||
|
||||
invar := &interfaces.ExclusiveInvariant{
|
||||
Invariants: ors, // one and only one of these should be true
|
||||
}
|
||||
invariants = append(invariants, invar)
|
||||
|
||||
return invariants, nil
|
||||
@@ -2379,7 +2379,13 @@ func (obj *StmtEdge) Output(table map[interfaces.Func]types.Value) (*interfaces.
|
||||
}
|
||||
|
||||
// StmtEdgeHalf represents half of an edge in the parsed edge representation.
|
||||
// This does not satisfy the Stmt interface.
|
||||
// This does not satisfy the Stmt interface. The `Name` value can be a single
|
||||
// string or a list of strings. The former will produce a single edge half, the
|
||||
// latter produces a list of resources. Using this list mechanism is a safe
|
||||
// alternative to traditional flow control like `for` loops. The `Name` value
|
||||
// can only be a single string when it can be detected statically. Otherwise, it
|
||||
// is assumed that a list of strings should be expected. More mechanisms to
|
||||
// determine if the value is static may be added over time.
|
||||
type StmtEdgeHalf struct {
|
||||
Kind string // kind of resource, eg: pkg, file, svc, etc...
|
||||
Name interfaces.Expr // unique name for the res of this kind
|
||||
@@ -2488,39 +2494,35 @@ func (obj *StmtEdgeHalf) Unify() ([]interfaces.Invariant, error) {
|
||||
}
|
||||
invariants = append(invariants, invars...)
|
||||
|
||||
invarStr := &interfaces.EqualsInvariant{
|
||||
Expr: obj.Name,
|
||||
Type: types.TypeStr,
|
||||
}
|
||||
|
||||
// Optimization: If we know it's an str, no need for exclusives!
|
||||
// TODO: Check other cases, like if it's a function call, and we know it
|
||||
// can only return a single string. (Eg: fmt.printf for example.)
|
||||
isString := false
|
||||
if _, ok := obj.Name.(*ExprStr); ok {
|
||||
invariants = append(invariants, invarStr)
|
||||
// It's a string! (A plain string was specified.)
|
||||
isString = true
|
||||
}
|
||||
if typ, err := obj.Name.Type(); err == nil {
|
||||
// It has type of string! (Might be an interpolation specified.)
|
||||
if typ.Cmp(types.TypeStr) == nil {
|
||||
isString = true
|
||||
}
|
||||
}
|
||||
if isString {
|
||||
invar := &interfaces.EqualsInvariant{
|
||||
Expr: obj.Name,
|
||||
Type: types.TypeStr,
|
||||
}
|
||||
invariants = append(invariants, invar)
|
||||
|
||||
return invariants, nil
|
||||
}
|
||||
|
||||
invarListStr := &interfaces.EqualsInvariant{
|
||||
// Down here, we only allow []str, no need for exclusives!
|
||||
invar := &interfaces.EqualsInvariant{
|
||||
Expr: obj.Name,
|
||||
Type: types.TypeListStr,
|
||||
}
|
||||
|
||||
// Optimization: If we know it's a []str, no need for exclusives!
|
||||
if expr, ok := obj.Name.(*ExprList); ok {
|
||||
typ, err := expr.Type()
|
||||
if err == nil && typ.Cmp(types.TypeListStr) == nil {
|
||||
invariants = append(invariants, invarListStr)
|
||||
return invariants, nil
|
||||
}
|
||||
}
|
||||
|
||||
// name must be a string or a list
|
||||
ors := []interfaces.Invariant{}
|
||||
ors = append(ors, invarStr)
|
||||
ors = append(ors, invarListStr)
|
||||
|
||||
invar := &interfaces.ExclusiveInvariant{
|
||||
Invariants: ors, // one and only one of these should be true
|
||||
}
|
||||
invariants = append(invariants, invar)
|
||||
|
||||
return invariants, nil
|
||||
|
||||
@@ -65,7 +65,7 @@ class base($config) {
|
||||
panic($prefix == "") # panic if prefix is empty
|
||||
panic(not strings.has_suffix($prefix, "/"))
|
||||
|
||||
file $prefix { # dir
|
||||
file "${prefix}" { # dir
|
||||
state => $const.res.file.state.exists,
|
||||
}
|
||||
$tftp_prefix = "${prefix}${tftp_suffix}"
|
||||
@@ -85,7 +85,7 @@ class base($config) {
|
||||
#
|
||||
# network
|
||||
#
|
||||
net $interface {
|
||||
net "${interface}" {
|
||||
state => $const.res.net.state.up,
|
||||
addrs => [$router,], # has cidr suffix
|
||||
#gateway => "192.168.42.1", # TODO: get upstream public gateway with new function
|
||||
@@ -130,10 +130,10 @@ class base($config) {
|
||||
}
|
||||
}
|
||||
|
||||
file $tftp_prefix { # dir
|
||||
file "${tftp_prefix}" { # dir
|
||||
state => $const.res.file.state.exists,
|
||||
}
|
||||
file $uefi_prefix { # dir
|
||||
file "${uefi_prefix}" { # dir
|
||||
state => $const.res.file.state.exists,
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ class base($config) {
|
||||
|
||||
# XXX: should this also be part of repo too?
|
||||
class tftp_root_file($f) {
|
||||
#tftp:file $f { # without root slash
|
||||
#tftp:file "${f}" { # without root slash
|
||||
tftp:file "/${f}" { # with root slash
|
||||
path => $syslinux_root + $f, # TODO: add autoedges
|
||||
|
||||
@@ -185,7 +185,7 @@ class base($config) {
|
||||
#
|
||||
# http
|
||||
#
|
||||
file $http_prefix { # dir
|
||||
file "${http_prefix}" { # dir
|
||||
state => $const.res.file.state.exists,
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ class base($config) {
|
||||
}
|
||||
|
||||
$kickstart_http_prefix = "${http_prefix}${kickstart_suffix}"
|
||||
file $kickstart_http_prefix {
|
||||
file "${kickstart_http_prefix}" {
|
||||
state => $const.res.file.state.exists,
|
||||
#source => "", # this default means empty directory
|
||||
recurse => true,
|
||||
@@ -237,21 +237,21 @@ class base:repo($config) {
|
||||
$distroarch_release_http_prefix = "${distroarch_http_prefix}release/"
|
||||
$distroarch_updates_http_prefix = "${distroarch_http_prefix}updates/"
|
||||
|
||||
file $distroarch_tftp_prefix { # dir
|
||||
file "${distroarch_tftp_prefix}" { # dir
|
||||
state => $const.res.file.state.exists,
|
||||
|
||||
#Meta:quiet => true, # TODO
|
||||
}
|
||||
file $distroarch_uefi_prefix { # dir
|
||||
file "${distroarch_uefi_prefix}" { # dir
|
||||
state => $const.res.file.state.exists,
|
||||
}
|
||||
file $distroarch_http_prefix { # root http dir
|
||||
file "${distroarch_http_prefix}" { # root http dir
|
||||
state => $const.res.file.state.exists,
|
||||
}
|
||||
file $distroarch_release_http_prefix {
|
||||
file "${distroarch_release_http_prefix}" {
|
||||
state => $const.res.file.state.exists,
|
||||
}
|
||||
file $distroarch_updates_http_prefix {
|
||||
file "${distroarch_updates_http_prefix}" {
|
||||
state => $const.res.file.state.exists,
|
||||
}
|
||||
|
||||
@@ -261,7 +261,7 @@ class base:repo($config) {
|
||||
$uefi_download_dir = "${distroarch_uefi_prefix}download/"
|
||||
$uefi_extract_dir = "${distroarch_uefi_prefix}extract/"
|
||||
|
||||
file $uefi_extract_dir { # mkdir
|
||||
file "${uefi_extract_dir}" { # mkdir
|
||||
state => $const.res.file.state.exists,
|
||||
|
||||
Depend => Exec["uefi-download-${uid}"],
|
||||
@@ -609,7 +609,7 @@ class base:host($name, $config) {
|
||||
}
|
||||
|
||||
$kickstart_file = "${kickstart_http_prefix}${hkey}.ks"
|
||||
file $kickstart_file {
|
||||
file "${kickstart_file}" {
|
||||
state => $const.res.file.state.exists,
|
||||
content => template(deploy.readfile("/files/kickstart.ks.tmpl"), $http_kickstart_template),
|
||||
}
|
||||
@@ -631,11 +631,11 @@ class base:host($name, $config) {
|
||||
#kv "${name}" {
|
||||
# key => $provision_key,
|
||||
#}
|
||||
#value $provision_key {
|
||||
#value "${provision_key}" {
|
||||
# #any => true, # bool
|
||||
#}
|
||||
#Http:Flag["${name}"].value -> Kv["${name}"].value
|
||||
#Http:Flag["${name}"].value -> Value[$provision_key].any
|
||||
#Http:Flag["${name}"].value -> Value["${provision_key}"].any
|
||||
##$st_provisioned = value.get_bool($provision_key)
|
||||
#$st_provisioned = value.get_str($provision_key)
|
||||
#$provisioned = $st_provisioned->ready and $st_provisioned->value == "true" # export this value to parent scope
|
||||
|
||||
@@ -18,8 +18,8 @@ $fn2 = funcgen(false)
|
||||
$out1 = $fn1()
|
||||
$out2 = $fn2()
|
||||
|
||||
test $out1 {}
|
||||
test $out2 {}
|
||||
test "${out1}" {}
|
||||
test "${out2}" {}
|
||||
-- OUTPUT --
|
||||
Edge: FuncValue -> call # fn
|
||||
Edge: FuncValue -> call # fn
|
||||
|
||||
@@ -3,11 +3,12 @@ import "fmt"
|
||||
|
||||
include c1([13, 42, 0, -37,])
|
||||
class c1($b) {
|
||||
test fmt.printf("len is: %d", len($b)) {} # len is 4
|
||||
test [fmt.printf("len is: %d", len($b)),] {} # len is 4
|
||||
}
|
||||
-- OUTPUT --
|
||||
Edge: FuncValue -> call # fn
|
||||
Edge: FuncValue -> call # fn
|
||||
Edge: call -> composite # 0
|
||||
Edge: const -> composite # 0
|
||||
Edge: const -> composite # 1
|
||||
Edge: const -> composite # 2
|
||||
@@ -17,6 +18,7 @@ Vertex: FuncValue
|
||||
Vertex: call
|
||||
Vertex: call
|
||||
Vertex: composite
|
||||
Vertex: composite
|
||||
Vertex: const
|
||||
Vertex: const
|
||||
Vertex: const
|
||||
|
||||
@@ -6,7 +6,7 @@ $some_value1 = 42 # or something more complex like the output of a slow function
|
||||
class foo($num) {
|
||||
# we should have a different `$inside` value for each use of this class
|
||||
$inside = $some_value1 + $some_value2 + 4
|
||||
test fmt.printf("test-%d-%d", $num, $inside) {} # some resource
|
||||
test [fmt.printf("test-%d-%d", $num, $inside),] {} # some resource
|
||||
}
|
||||
$some_value2 = 13 # check that non-ordering works too!
|
||||
|
||||
@@ -24,6 +24,9 @@ Edge: FuncValue -> call # fn
|
||||
Edge: FuncValue -> call # fn
|
||||
Edge: FuncValue -> call # fn
|
||||
Edge: FuncValue -> call # fn
|
||||
Edge: call -> composite # 0
|
||||
Edge: call -> composite # 0
|
||||
Edge: call -> composite # 0
|
||||
Vertex: FuncValue
|
||||
Vertex: FuncValue
|
||||
Vertex: FuncValue
|
||||
@@ -42,6 +45,9 @@ Vertex: call
|
||||
Vertex: call
|
||||
Vertex: call
|
||||
Vertex: call
|
||||
Vertex: composite
|
||||
Vertex: composite
|
||||
Vertex: composite
|
||||
Vertex: const
|
||||
Vertex: const
|
||||
Vertex: const
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
include c1("t1")
|
||||
include c1("t2")
|
||||
class c1($a) {
|
||||
test $a {
|
||||
test "${a}" {
|
||||
stringptr => $foo,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ $prefixer = func($x) {
|
||||
$out1 = $prefixer("a")
|
||||
$out2 = $prefixer("b")
|
||||
|
||||
test $out1 {} # helloa
|
||||
test $out2 {} # hellob
|
||||
test "${out1}" {} # helloa
|
||||
test "${out2}" {} # hellob
|
||||
-- OUTPUT --
|
||||
Edge: FuncValue -> call # fn
|
||||
Edge: FuncValue -> call # fn
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
-- main.mcl --
|
||||
# this is an empty list of test resources, iow test resources
|
||||
# this must pass type unification
|
||||
# this can only currently pass if we allow recursive unification solving
|
||||
# if we do, then the function graph is: `Vertex: list()` otherwise it's an error
|
||||
# This is an empty list of test resources, iow test resources. This must pass
|
||||
# type unification. This previously only passed if we allowed recursive
|
||||
# unification solving, but now we can support it without that.
|
||||
test [] {}
|
||||
-- OUTPUT --
|
||||
# err: errUnify: only recursive solutions left
|
||||
Vertex: composite
|
||||
|
||||
@@ -9,8 +9,8 @@ $prefixer = func($x) {
|
||||
$out1 = $prefixer("world")
|
||||
$out2 = $prefixer($out1)
|
||||
|
||||
test $out1 {}
|
||||
test $out2 {}
|
||||
test "${out1}" {}
|
||||
test "${out2}" {}
|
||||
-- OUTPUT --
|
||||
Edge: FuncValue -> call # fn
|
||||
Edge: FuncValue -> call # fn
|
||||
|
||||
@@ -5,7 +5,7 @@ import "fmt"
|
||||
include c1("t1", "hello") # len is 5
|
||||
include c1("t2", [13, 42, 0, -37,]) # len is 4
|
||||
class c1($a, $b) {
|
||||
test $a {
|
||||
test "${a}" {
|
||||
anotherstr => fmt.printf("len is: %d", len($b)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ include c1("t2", [13, 42, 0, -37,]) # len is 4
|
||||
|
||||
# specifying a fixed type for $b is a compile error, because it's sometimes str!
|
||||
class c1($a, $b []str) {
|
||||
test $a {
|
||||
test "${a}" {
|
||||
anotherstr => fmt.printf("len is: %d", len($b)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ func funcgen() {
|
||||
$fn = funcgen()
|
||||
$out = $fn()
|
||||
|
||||
test $out {}
|
||||
test "${out}" {}
|
||||
-- OUTPUT --
|
||||
Edge: FuncValue -> call # fn
|
||||
Edge: call -> call # fn
|
||||
|
||||
@@ -8,7 +8,7 @@ $funcgen = func() {
|
||||
$fn = $funcgen()
|
||||
$out = $fn()
|
||||
|
||||
test $out {}
|
||||
test "${out}" {}
|
||||
-- OUTPUT --
|
||||
Edge: FuncValue -> call # fn
|
||||
Edge: call -> call # fn
|
||||
|
||||
@@ -4,7 +4,7 @@ $x = "hello"
|
||||
if true {
|
||||
$x = "world" # shadowed
|
||||
}
|
||||
test $x {}
|
||||
test "${x}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: const
|
||||
Vertex: const
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
$x = "hello"
|
||||
if true {
|
||||
$x = "world" # shadowed
|
||||
test $x {}
|
||||
test "${x}" {}
|
||||
}
|
||||
-- OUTPUT --
|
||||
Vertex: const
|
||||
|
||||
@@ -5,7 +5,7 @@ func answer() {
|
||||
|
||||
$out1 = answer()
|
||||
|
||||
test $out1 {}
|
||||
test "${out1}" {}
|
||||
-- OUTPUT --
|
||||
Edge: FuncValue -> call # fn
|
||||
Vertex: FuncValue
|
||||
|
||||
@@ -6,15 +6,17 @@ func answer() {
|
||||
$out1 = answer()
|
||||
$out2 = answer()
|
||||
|
||||
test $out1 + $out2 {}
|
||||
test [$out1 + $out2,] {}
|
||||
-- OUTPUT --
|
||||
Edge: FuncValue -> call # fn
|
||||
Edge: FuncValue -> call # fn
|
||||
Edge: FuncValue -> call # fn
|
||||
Edge: call -> composite # 0
|
||||
Vertex: FuncValue
|
||||
Vertex: FuncValue
|
||||
Vertex: FuncValue
|
||||
Vertex: call
|
||||
Vertex: call
|
||||
Vertex: call
|
||||
Vertex: composite
|
||||
Vertex: const
|
||||
|
||||
@@ -8,7 +8,7 @@ $answer = func() {
|
||||
|
||||
$out = $answer()
|
||||
|
||||
test $out {}
|
||||
test "${out}" {}
|
||||
-- OUTPUT --
|
||||
Edge: FuncValue -> call # fn
|
||||
Vertex: FuncValue
|
||||
|
||||
@@ -9,14 +9,16 @@ $answer = func() {
|
||||
$out1 = $answer()
|
||||
$out2 = $answer()
|
||||
|
||||
test $out1 + $out2 {}
|
||||
test [$out1 + $out2,] {}
|
||||
-- OUTPUT --
|
||||
Edge: FuncValue -> call # fn
|
||||
Edge: FuncValue -> call # fn
|
||||
Edge: FuncValue -> call # fn
|
||||
Edge: call -> composite # 0
|
||||
Vertex: FuncValue
|
||||
Vertex: FuncValue
|
||||
Vertex: call
|
||||
Vertex: call
|
||||
Vertex: call
|
||||
Vertex: composite
|
||||
Vertex: const
|
||||
|
||||
@@ -11,6 +11,6 @@ $fn = if $some_bool {
|
||||
}
|
||||
|
||||
$out = $fn("wide")
|
||||
test $out {}
|
||||
test "${out}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[worldwide]
|
||||
|
||||
@@ -11,6 +11,6 @@ $fn = if $some_bool {
|
||||
}
|
||||
|
||||
$out = $fn(false)
|
||||
test $out {}
|
||||
test "${out}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[world]
|
||||
|
||||
@@ -11,6 +11,6 @@ $fn1 = funcgen()
|
||||
$fn2 = $fn1()
|
||||
$out = $fn2()
|
||||
|
||||
test $out {}
|
||||
test "${out}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[hello]
|
||||
|
||||
@@ -15,6 +15,6 @@ $fn2 = $fn1()
|
||||
$fn3 = $fn2()
|
||||
$out = $fn3()
|
||||
|
||||
test $out {}
|
||||
test "${out}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[hello]
|
||||
|
||||
@@ -33,10 +33,15 @@ $out2 = $fn1("there")
|
||||
$out3 = $fn2("hello")
|
||||
$out4 = $fn2("world")
|
||||
|
||||
test $out1() {} # hey
|
||||
test $out2() {} # there
|
||||
test $out3() {} # wow: hello
|
||||
test $out4() {} # wow: world
|
||||
$name1 = $out1()
|
||||
$name2 = $out2()
|
||||
$name3 = $out3()
|
||||
$name4 = $out4()
|
||||
|
||||
test [$name1,] {} # hey
|
||||
test [$name2,] {} # there
|
||||
test [$name3,] {} # wow: hello
|
||||
test [$name4,] {} # wow: world
|
||||
-- OUTPUT --
|
||||
Vertex: test[hey]
|
||||
Vertex: test[there]
|
||||
|
||||
@@ -5,6 +5,6 @@ $zero = 0
|
||||
$one = $zero + 1
|
||||
$two = $one + 1 # needs a chain to panic
|
||||
|
||||
test fmt.printf("%d%d%d", $zero, $one, $two) {}
|
||||
test [fmt.printf("%d%d%d", $zero, $one, $two),] {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[012]
|
||||
|
||||
@@ -18,8 +18,8 @@ $fn2 = funcgen(false)
|
||||
$out1 = $fn1()
|
||||
$out2 = $fn2()
|
||||
|
||||
test $out1 {}
|
||||
test $out2 {}
|
||||
test "${out1}" {}
|
||||
test "${out2}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[hello]
|
||||
Vertex: test[world]
|
||||
|
||||
@@ -18,8 +18,8 @@ $fn2 = $funcgen(false)
|
||||
$out1 = $fn1()
|
||||
$out2 = $fn2()
|
||||
|
||||
test $out1 {}
|
||||
test $out2 {}
|
||||
test "${out1}" {}
|
||||
test "${out2}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[hello]
|
||||
Vertex: test[world]
|
||||
|
||||
@@ -36,10 +36,15 @@ $out2 = $fn1("world")
|
||||
$out3 = $fn2("hello")
|
||||
$out4 = $fn2("world")
|
||||
|
||||
test $out1() {}
|
||||
test $out2() {}
|
||||
test $out3() {}
|
||||
test $out4() {}
|
||||
$name1 = $out1()
|
||||
$name2 = $out2()
|
||||
$name3 = $out3()
|
||||
$name4 = $out4()
|
||||
|
||||
test "${name1}" {}
|
||||
test "${name2}" {}
|
||||
test "${name3}" {}
|
||||
test "${name4}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[true-true]
|
||||
Vertex: test[true-false]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
-- main.mcl --
|
||||
$x1 = "t1"
|
||||
class foo {
|
||||
test $x1 {}
|
||||
test "${x1}" {}
|
||||
}
|
||||
include foo
|
||||
-- OUTPUT --
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
-- main.mcl --
|
||||
include foo
|
||||
class foo {
|
||||
test $x1 {}
|
||||
test "${x1}" {}
|
||||
}
|
||||
$x1 = "t1"
|
||||
-- OUTPUT --
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
-- main.mcl --
|
||||
$x1 = "bad1"
|
||||
class foo($x1) {
|
||||
test $x1 {}
|
||||
test "${x1}" {}
|
||||
}
|
||||
include foo("t1")
|
||||
-- OUTPUT --
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
-- main.mcl --
|
||||
$x1 = "t1"
|
||||
class foo {
|
||||
test $x1 {}
|
||||
test $x2 {}
|
||||
test "${x1}" {}
|
||||
test "${x2}" {}
|
||||
}
|
||||
include foo
|
||||
$x2 = "t2"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
-- main.mcl --
|
||||
$x1 = "bad1"
|
||||
class foo($x1, $x2) {
|
||||
test "t1: " + $x2 {} # swapped
|
||||
test "t2: " + $x1 {}
|
||||
test ["t1: " + $x2,] {} # swapped
|
||||
test ["t2: " + $x1,] {}
|
||||
}
|
||||
include foo($x2, "t1")
|
||||
$x2 = "t2"
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
$x1 = "bad1"
|
||||
class foo($x1, $x2) {
|
||||
include bar
|
||||
test "t1: " + $x1 {}
|
||||
test "t2: " + $x2 {}
|
||||
test ["t1: " + $x1,] {}
|
||||
test ["t2: " + $x2,] {}
|
||||
class bar {
|
||||
test "t0: " + $x0 {}
|
||||
test ["t0: " + $x0,] {}
|
||||
}
|
||||
}
|
||||
include foo("t1", $x2)
|
||||
|
||||
@@ -6,7 +6,7 @@ include defs.foo
|
||||
import "defs.mcl" # out of order for fun
|
||||
-- defs.mcl --
|
||||
class foo {
|
||||
test $x1 {} # capture the var
|
||||
test "${x1}" {} # capture the var
|
||||
}
|
||||
$x1 = "t1"
|
||||
-- OUTPUT --
|
||||
|
||||
@@ -10,8 +10,8 @@ class c1 {
|
||||
include c1 as i1 # has $y
|
||||
include i1.c0 as i0 # has $x ...and $y
|
||||
|
||||
test $i0.x {} # ok
|
||||
test $i1.y {} # ok
|
||||
test "${i0.x}" {} # ok
|
||||
test "${i1.y}" {} # ok
|
||||
panic($i0.x != "goodbye")
|
||||
panic($i1.y != "hello")
|
||||
|
||||
@@ -21,7 +21,7 @@ panic($i1.y != "hello")
|
||||
# current child scope, which makes this variable visible. Unfortunately, it does
|
||||
# not have the correct dependency (edge) present in the Ordering system, so it
|
||||
# is flaky depending on luck of the toposort.
|
||||
#test $i0.y {}
|
||||
#test "${i0.y}" {}
|
||||
|
||||
-- OUTPUT --
|
||||
Vertex: test[goodbye]
|
||||
|
||||
@@ -26,8 +26,11 @@ include i1.c0 as i01
|
||||
include c1(false) as i2
|
||||
include i2.c0 as i02
|
||||
|
||||
test $i01.x {}
|
||||
test $i02.x {}
|
||||
$name1 = $i01.x
|
||||
$name2 = $i02.x
|
||||
|
||||
test "${name1}" {}
|
||||
test "${name2}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[hello]
|
||||
Vertex: test[goodbye]
|
||||
|
||||
@@ -6,6 +6,6 @@ class c1() {
|
||||
# TODO: can this be allowed?
|
||||
include c1 as i1
|
||||
include c1 as i1
|
||||
test $i1.x {}
|
||||
test "${i1.x}" {}
|
||||
-- OUTPUT --
|
||||
# err: errSetScope: could not generate ordering: duplicate assignment to `scoped:i1`, have: include(c1)
|
||||
|
||||
@@ -6,6 +6,6 @@ class c1($s) {
|
||||
# TODO: can this be allowed?
|
||||
include c1("hey") as i1
|
||||
include c1("hey") as i1
|
||||
test $i1.x {}
|
||||
test "${i1.x}" {}
|
||||
-- OUTPUT --
|
||||
# err: errSetScope: could not generate ordering: duplicate assignment to `scoped:i1`, have: include(c1)
|
||||
|
||||
@@ -5,6 +5,6 @@ class c1($s) {
|
||||
|
||||
include c1("hey") as i1
|
||||
include c1("there") as i1
|
||||
test $i1.x {}
|
||||
test "${i1.x}" {}
|
||||
-- OUTPUT --
|
||||
# err: errSetScope: could not generate ordering: duplicate assignment to `scoped:i1`, have: include(c1)
|
||||
|
||||
@@ -8,7 +8,7 @@ class c1 {
|
||||
}
|
||||
include c1 as i1
|
||||
|
||||
test i1.f1("world") {}
|
||||
test [i1.f1("world"),] {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[helloworld]
|
||||
Vertex: test[t1]
|
||||
|
||||
@@ -8,7 +8,7 @@ class c1 {
|
||||
}
|
||||
include c1 as i1
|
||||
|
||||
test i1.f1("whatever") {}
|
||||
test [i1.f1("whatever"),] {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[helloworld]
|
||||
Vertex: test[t1]
|
||||
|
||||
@@ -7,7 +7,7 @@ class c1 {
|
||||
}
|
||||
include c1 as i1
|
||||
|
||||
test i1.f1() {}
|
||||
test [i1.f1(),] {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[hello]
|
||||
Vertex: test[t1]
|
||||
|
||||
@@ -17,8 +17,8 @@ class c1($b) {
|
||||
include c1(true) as i1
|
||||
include c1(false) as i2
|
||||
|
||||
test i1.f1() {}
|
||||
test i2.f1() {}
|
||||
test [i1.f1(),] {}
|
||||
test [i2.f1(),] {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[hello]
|
||||
Vertex: test[goodbye]
|
||||
|
||||
@@ -27,10 +27,10 @@ class c1($b) {
|
||||
include c1(true) as i1
|
||||
include c1(false) as i2
|
||||
|
||||
test i1.f1() {}
|
||||
test i2.f1() {}
|
||||
test i1.i0.f0() {} # I think these might work directly too. Do we want them to?
|
||||
test i2.i0.f0() {}
|
||||
test [i1.f1(),] {}
|
||||
test [i2.f1(),] {}
|
||||
test [i1.i0.f0(),] {} # I think these might work directly too. Do we want them to?
|
||||
test [i2.i0.f0(),] {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[goodbye]
|
||||
Vertex: test[hello]
|
||||
|
||||
@@ -5,6 +5,6 @@ class c1($s) {
|
||||
}
|
||||
|
||||
include c1("hey") as i1
|
||||
test $i1.x {}
|
||||
test "${i1.x}" {}
|
||||
-- OUTPUT --
|
||||
# err: errSetScope: could not generate ordering: duplicate assignment to `scoped:i1`, have: import(fmt)
|
||||
|
||||
@@ -5,6 +5,6 @@ class c1($s) {
|
||||
}
|
||||
|
||||
include c1("hey") as fmt
|
||||
test $fmt.x {}
|
||||
test "${fmt.x}" {}
|
||||
-- OUTPUT --
|
||||
# err: errSetScope: could not generate ordering: duplicate assignment to `scoped:fmt`, have: import(fmt)
|
||||
|
||||
@@ -8,7 +8,9 @@ class c1 {
|
||||
}
|
||||
include c1 as i1
|
||||
|
||||
test $i1.f1("world") {}
|
||||
$name = $i1.f1("world")
|
||||
|
||||
test "${name}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[helloworld]
|
||||
Vertex: test[t1]
|
||||
|
||||
@@ -8,7 +8,9 @@ class c1 {
|
||||
}
|
||||
include c1 as i1
|
||||
|
||||
test $i1.f1("whatever") {}
|
||||
$name = $i1.f1("whatever")
|
||||
|
||||
test "${name}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[helloworld]
|
||||
Vertex: test[t1]
|
||||
|
||||
@@ -7,7 +7,9 @@ class c1 {
|
||||
}
|
||||
include c1 as i1
|
||||
|
||||
test $i1.f1() {}
|
||||
$name = $i1.f1()
|
||||
|
||||
test "${name}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[hello]
|
||||
Vertex: test[t1]
|
||||
|
||||
@@ -17,8 +17,11 @@ class c1($b) {
|
||||
include c1(true) as i1
|
||||
include c1(false) as i2
|
||||
|
||||
test $i1.f1() {}
|
||||
test $i2.f1() {}
|
||||
$name1 = $i1.f1()
|
||||
$name2 = $i2.f1()
|
||||
|
||||
test "${name1}" {}
|
||||
test "${name2}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[hello]
|
||||
Vertex: test[goodbye]
|
||||
|
||||
@@ -28,11 +28,17 @@ class c1($b) {
|
||||
include c1(true) as i1
|
||||
include c1(false) as i2
|
||||
|
||||
test $i1.x() {}
|
||||
test $i1.i0.f0() {}
|
||||
test $i2.x() {}
|
||||
test $i1.i0.f0() {} # I think these should work directly too. Do we want them to?
|
||||
test $i2.i0.f0() {}
|
||||
$name1 = $i1.x()
|
||||
$name2 = $i1.i0.f0()
|
||||
$name3 = $i2.x()
|
||||
$name4 = $i1.i0.f0() # I think these should work directly too. Do we want them to?
|
||||
$name5 = $i2.i0.f0()
|
||||
|
||||
test "${name1}" {}
|
||||
test "${name2}" {}
|
||||
test "${name3}" {}
|
||||
test "${name4}" {}
|
||||
test "${name5}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[goodbye]
|
||||
Vertex: test[hello]
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
-- main.mcl --
|
||||
$top = "top-level"
|
||||
class base($s) {
|
||||
test "middle " + $s {}
|
||||
test ["middle " + $s,] {}
|
||||
$middle = "inside base"
|
||||
}
|
||||
|
||||
# syntactic sugar for the equivalent of defining a class `inner` inside of base.
|
||||
class base:inner($s) {
|
||||
test "inner " + $s {}
|
||||
test ["inner " + $s,] {}
|
||||
|
||||
$last = "i am inner and i can see " + $middle
|
||||
}
|
||||
@@ -15,9 +15,9 @@ class base:inner($s) {
|
||||
include base("world") as b1
|
||||
include b1.inner("hello") as b2 # inner comes out of `base`
|
||||
|
||||
test $top {}
|
||||
test $b1.middle {}
|
||||
test $b2.last {}
|
||||
test "${top}" {}
|
||||
test "${b1.middle}" {}
|
||||
test "${b2.last}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[inner hello]
|
||||
Vertex: test[middle world]
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
-- main.mcl --
|
||||
$top = "top-level"
|
||||
class base($s) {
|
||||
test "middle " + $s {}
|
||||
test ["middle " + $s,] {}
|
||||
$middle = "inside base"
|
||||
}
|
||||
|
||||
# syntactic sugar for the equivalent of defining a class `inner` inside of base.
|
||||
class base:inner1($s) {
|
||||
test "inner1 " + $s {}
|
||||
test ["inner1 " + $s,] {}
|
||||
|
||||
$last = "i am inner1 and i can see " + $middle
|
||||
}
|
||||
|
||||
class base:inner2($s) {
|
||||
test "inner2 " + $s {}
|
||||
test ["inner2 " + $s,] {}
|
||||
|
||||
$last = "i am inner2 and i can see " + $middle
|
||||
}
|
||||
|
||||
# three deep!
|
||||
class base:inner1:deep($s, $b) {
|
||||
test "deep is " + $s {}
|
||||
test ["deep is " + $s,] {}
|
||||
|
||||
$end = "i am deep and i can see " + $middle + " and last says " + $last
|
||||
}
|
||||
@@ -30,11 +30,11 @@ include b0.inner1("hello") as b1 # inner comes out of `base`
|
||||
include b0.inner2("hello") as b2 # inner comes out of `base`
|
||||
include b1.deep("deep", true) as d # deep comes out of `inner1`
|
||||
|
||||
test $top {}
|
||||
test $b0.middle {}
|
||||
test $b1.last {}
|
||||
test $b2.last {}
|
||||
test $d.end {}
|
||||
test "${top}" {}
|
||||
test "${b0.middle}" {}
|
||||
test "${b1.last}" {}
|
||||
test "${b2.last}" {}
|
||||
test "${d.end}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[deep is deep]
|
||||
Vertex: test[i am deep and i can see inside base and last says i am inner1 and i can see inside base]
|
||||
|
||||
@@ -5,7 +5,7 @@ class c1 {
|
||||
}
|
||||
include c1 as i1
|
||||
|
||||
test $i1.x {}
|
||||
test "${i1.x}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[hello]
|
||||
Vertex: test[t1]
|
||||
|
||||
@@ -15,8 +15,8 @@ class c1($b) {
|
||||
include c1(true) as i1
|
||||
include c1(false) as i2
|
||||
|
||||
test $i1.x {}
|
||||
test $i2.x {}
|
||||
test "${i1.x}" {}
|
||||
test "${i2.x}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[hello]
|
||||
Vertex: test[goodbye]
|
||||
|
||||
@@ -25,10 +25,10 @@ class c1($b) {
|
||||
include c1(true) as i1
|
||||
include c1(false) as i2
|
||||
|
||||
test $i1.x {}
|
||||
test $i2.x {}
|
||||
test $i1.i0.y {} # I think these should work directly too. Do we want them to?
|
||||
test $i2.i0.y {}
|
||||
test "${i1.x}" {}
|
||||
test "${i2.x}" {}
|
||||
test "${i1.i0.y}" {} # I think these should work directly too. Do we want them to?
|
||||
test "${i2.i0.y}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[goodbye]
|
||||
Vertex: test[hello]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
-- main.mcl --
|
||||
$wat = "bad1"
|
||||
class c1($wat) {
|
||||
test $wat {}
|
||||
test "${wat}" {}
|
||||
}
|
||||
include c1("hello")
|
||||
-- OUTPUT --
|
||||
|
||||
@@ -4,7 +4,7 @@ class shadowme($msg) {
|
||||
$msg = "c"
|
||||
if true {
|
||||
$msg = "d" # this is used!
|
||||
test $msg {}
|
||||
test "${msg}" {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ class shadowme($msg) {
|
||||
if true {
|
||||
$msg = "d"
|
||||
}
|
||||
test $msg {}
|
||||
test "${msg}" {}
|
||||
}
|
||||
|
||||
include shadowme("b")
|
||||
|
||||
@@ -15,7 +15,7 @@ include c1(true)
|
||||
# error prone, and also require a higher-order FRP, which would add complexity
|
||||
# but little value.
|
||||
|
||||
test $foo {}
|
||||
test "${foo}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[a]
|
||||
Vertex: test[hello]
|
||||
|
||||
@@ -4,6 +4,7 @@ $f = func($x) {
|
||||
$wat
|
||||
}
|
||||
|
||||
test $f("foo") {}
|
||||
$name = $f("foo")
|
||||
test "${name}" {}
|
||||
-- OUTPUT --
|
||||
# err: errSetScope: variable x not in scope
|
||||
|
||||
@@ -26,9 +26,9 @@ $out1 = $fn("user")
|
||||
$out2 = $fn("james")
|
||||
$out3 = $fn("")
|
||||
|
||||
test $out1 {}
|
||||
test $out2 {}
|
||||
test $out3 {}
|
||||
test "${out1}" {}
|
||||
test "${out2}" {}
|
||||
test "${out3}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[hello purpleidea]
|
||||
Vertex: test[hello user]
|
||||
|
||||
@@ -16,8 +16,10 @@ $generate = func($idn) {
|
||||
|
||||
$foo = iter.map([$id1, $id2,], $generate)
|
||||
|
||||
test $foo[0] || "fail" {}
|
||||
test $foo[1] || "fail" {}
|
||||
$name0 = $foo[0] || "fail"
|
||||
$name1 = $foo[1] || "fail"
|
||||
test "${name0}" {}
|
||||
test "${name1}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[foo]
|
||||
Vertex: test[foofoo]
|
||||
|
||||
@@ -24,8 +24,8 @@ $funcgen = func() {
|
||||
}
|
||||
}
|
||||
|
||||
test $out1 {}
|
||||
test $out2 {}
|
||||
test "${out1}" {}
|
||||
test "${out2}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[so true]
|
||||
Vertex: test[so false]
|
||||
|
||||
@@ -24,8 +24,8 @@ $fn = if $some_bool {
|
||||
$out1 = $fn(true)
|
||||
$out2 = $fn(false)
|
||||
|
||||
test $out1 {}
|
||||
test $out2 {}
|
||||
test "${out1}" {}
|
||||
test "${out2}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[so true]
|
||||
Vertex: test[so false]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
-- main.mcl --
|
||||
# this magic string variable should exist and be "exists"
|
||||
test $const.res.file.state.exists {}
|
||||
test "${const.res.file.state.exists}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[exists]
|
||||
|
||||
@@ -12,6 +12,7 @@ $id = func($y) { $y }
|
||||
# since $apply changes over time, this call needs a dynamic sub-graph. In
|
||||
# theory, the $f calls above do not need a sub-graph, but does our optimization
|
||||
# support this corner case yet?
|
||||
test $apply($id, "foo") {}
|
||||
$name = $apply($id, "foo")
|
||||
test "${name}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[foo]
|
||||
|
||||
@@ -32,10 +32,10 @@ $s4 = if contains([42, 13, 0,], $intlists) {
|
||||
"passed4"
|
||||
}
|
||||
|
||||
test $s1 {} # passed
|
||||
test $s2 {} # passed
|
||||
test $s3 {} # passed
|
||||
test $s4 {} # passed
|
||||
test "${s1}" {} # passed
|
||||
test "${s2}" {} # passed
|
||||
test "${s3}" {} # passed
|
||||
test "${s4}" {} # passed
|
||||
-- OUTPUT --
|
||||
Vertex: test[passed1]
|
||||
Vertex: test[passed2]
|
||||
|
||||
@@ -12,8 +12,10 @@ $call_f1 = func($x) {
|
||||
$call_f2 = func($x) {
|
||||
$f2() + $x
|
||||
}
|
||||
test $call_f1("!") {}
|
||||
test $call_f2("?") {}
|
||||
$name1 = $call_f1("!")
|
||||
$name2 = $call_f2("?")
|
||||
test "${name1}" {}
|
||||
test "${name2}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[top-level1!]
|
||||
Vertex: test[top-level2?]
|
||||
|
||||
@@ -41,9 +41,9 @@ if $x3 != $mod1.x3 {
|
||||
}
|
||||
|
||||
# hide the newlines from our output
|
||||
test strings.trim_space($x1) {}
|
||||
test strings.trim_space($x2) {}
|
||||
test strings.trim_space($x3) {}
|
||||
test [strings.trim_space($x1),] {}
|
||||
test [strings.trim_space($x2),] {}
|
||||
test [strings.trim_space($x3),] {}
|
||||
# debugging:
|
||||
#test "f1" {
|
||||
# anotherstr => $x1,
|
||||
|
||||
@@ -41,9 +41,9 @@ if $x3 != $mod1.x3 {
|
||||
}
|
||||
|
||||
# hide the newlines from our output
|
||||
test strings.trim_space($x1) {}
|
||||
test strings.trim_space($x2) {}
|
||||
test strings.trim_space($x3) {}
|
||||
test [strings.trim_space($x1),] {}
|
||||
test [strings.trim_space($x2),] {}
|
||||
test [strings.trim_space($x3),] {}
|
||||
# debugging:
|
||||
#test "f1" {
|
||||
# anotherstr => $x1,
|
||||
|
||||
@@ -31,8 +31,8 @@ if $x2 != $second.x2 {
|
||||
}
|
||||
|
||||
# hide the newlines from our output
|
||||
test strings.trim_space($x1) {}
|
||||
test strings.trim_space($x2) {}
|
||||
test [strings.trim_space($x1),] {}
|
||||
test [strings.trim_space($x2),] {}
|
||||
-- second.mcl --
|
||||
import "deploy"
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ if $x1 != deploy.readfile($f1) {
|
||||
}
|
||||
|
||||
# hide the newlines from our output
|
||||
test strings.trim_space($x1) {}
|
||||
test [strings.trim_space($x1),] {}
|
||||
-- files/file1 --
|
||||
This is file1 in the files/ folder.
|
||||
-- OUTPUT --
|
||||
|
||||
@@ -9,7 +9,7 @@ $f1 = "/files/file1"
|
||||
$x1 = deploy.readfileabs($f1)
|
||||
|
||||
# hide the newlines from our output
|
||||
test $x1 {}
|
||||
test "${x1}" {}
|
||||
-- files/file1 --
|
||||
This is file1 in the files/ folder.
|
||||
-- OUTPUT --
|
||||
|
||||
@@ -8,8 +8,8 @@ func prefixer($x) {
|
||||
$out1 = prefixer("a")
|
||||
$out2 = prefixer("b")
|
||||
|
||||
test $out1 {} # hello:a
|
||||
test $out2 {} # hello:b
|
||||
test "${out1}" {} # hello:a
|
||||
test "${out2}" {} # hello:b
|
||||
-- OUTPUT --
|
||||
Vertex: test[hello:a]
|
||||
Vertex: test[hello:b]
|
||||
|
||||
@@ -7,8 +7,8 @@ $prefixer = func($x) {
|
||||
$out1 = $prefixer("a")
|
||||
$out2 = $prefixer("b")
|
||||
|
||||
test $out1 {} # helloa
|
||||
test $out2 {} # hellob
|
||||
test "${out1}" {} # helloa
|
||||
test "${out2}" {} # hellob
|
||||
-- OUTPUT --
|
||||
Vertex: test[helloa]
|
||||
Vertex: test[hellob]
|
||||
|
||||
6
lang/interpret_test/TestAstFunc2/empty-res-list-0.txtar
Normal file
6
lang/interpret_test/TestAstFunc2/empty-res-list-0.txtar
Normal file
@@ -0,0 +1,6 @@
|
||||
-- main.mcl --
|
||||
# This is an empty list of test resources, iow test resources. This must pass
|
||||
# type unification. This previously only passed if we allowed recursive
|
||||
# unification solving, but now we can support it without that.
|
||||
test [] {}
|
||||
-- OUTPUT --
|
||||
@@ -3,7 +3,7 @@ some comment can go here!
|
||||
-- main.mcl --
|
||||
import "fmt"
|
||||
|
||||
test fmt.printf("answer: %d", 42) {}
|
||||
test [fmt.printf("answer: %d", 42),] {}
|
||||
-- files/file1 --
|
||||
this is file1
|
||||
-- files/file2 --
|
||||
|
||||
@@ -3,8 +3,8 @@ import "fmt"
|
||||
import "math"
|
||||
# FIXME: floats don't print nicely: https://github.com/golang/go/issues/46118
|
||||
# FIXME: This means that we see "42" for both, instead of 42.0 ...
|
||||
test fmt.printf("int: %d", math.fortytwo()) {}
|
||||
test fmt.printf("float: %f", math.fortytwo()) {}
|
||||
test [fmt.printf("int: %d", math.fortytwo()),] {}
|
||||
test [fmt.printf("float: %f", math.fortytwo()),] {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[float: 42]
|
||||
Vertex: test[int: 42]
|
||||
|
||||
@@ -6,6 +6,6 @@ func stradd($x) {
|
||||
|
||||
$x1 = stradd("hey")
|
||||
|
||||
test $x1 {}
|
||||
test "${x1}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[heyhey]
|
||||
|
||||
@@ -9,6 +9,6 @@ class funcgen1 {
|
||||
}
|
||||
include funcgen1
|
||||
$x1 = fun1() # not funcgen1.fun1 since it's *not* an import!
|
||||
test $x1 {} # hi
|
||||
test "${x1}" {} # hi
|
||||
-- OUTPUT --
|
||||
# err: errSetScope: func `fun1` does not exist in this scope
|
||||
|
||||
@@ -12,6 +12,6 @@ $const2 = "world" # added here to confirm any-order rules
|
||||
|
||||
include funcgen2
|
||||
$x2 = fun2() # not funcgen2.fun2 since it's *not* an import!
|
||||
test $x2 {} # hello world
|
||||
test "${x2}" {} # hello world
|
||||
-- OUTPUT --
|
||||
# err: errSetScope: func `fun2` does not exist in this scope
|
||||
|
||||
@@ -10,6 +10,6 @@ func sq1($x) {
|
||||
|
||||
$x1 = sq1(3) # 3^2 + 4 = 13
|
||||
|
||||
test fmt.printf("sq1: %d", $x1) {}
|
||||
test [fmt.printf("sq1: %d", $x1),] {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[sq1: 6]
|
||||
|
||||
@@ -11,7 +11,7 @@ func sq1($x) {
|
||||
|
||||
$x1 = sq1(math.fortytwo())
|
||||
|
||||
test fmt.printf("sq1: %d", $x1) {}
|
||||
test [fmt.printf("sq1: %d", $x1),] {}
|
||||
|
||||
-- OUTPUT --
|
||||
Vertex: test[sq1: 45]
|
||||
|
||||
@@ -8,6 +8,6 @@ func stradd($x) {
|
||||
|
||||
$x1 = stradd("hey")
|
||||
|
||||
test $x1 {}
|
||||
test "${x1}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[heythere]
|
||||
|
||||
@@ -3,6 +3,6 @@ $foo = "bad1"
|
||||
func bar($foo) {
|
||||
"hello " + $foo # shadows parent var
|
||||
}
|
||||
test bar("world") {}
|
||||
test [bar("world"),] {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[hello world]
|
||||
|
||||
@@ -3,6 +3,7 @@ $foo = "bad1"
|
||||
$bar = func($foo) {
|
||||
"hello " + $foo # shadows parent var
|
||||
}
|
||||
test $bar("world") {}
|
||||
$name = $bar("world")
|
||||
test "${name}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[hello world]
|
||||
|
||||
@@ -8,6 +8,6 @@ func stradd($x) {
|
||||
|
||||
$x1 = stradd("hey")
|
||||
|
||||
test $x1 {}
|
||||
test "${x1}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[nothing]
|
||||
|
||||
@@ -31,15 +31,16 @@ $funcgen3 = func() {
|
||||
|
||||
$fn1 = $funcgen1()
|
||||
$out1 = $fn1("hello")
|
||||
test $out1 {}
|
||||
test "${out1}" {}
|
||||
|
||||
$fn2 = $funcgen2()
|
||||
$out2 = $fn2("hello")
|
||||
test $out2 {}
|
||||
test "${out2}" {}
|
||||
|
||||
$fn3 = $funcgen3()
|
||||
$out3 = $fn3("goodbye")
|
||||
test $out3() {}
|
||||
$name3 = $out3()
|
||||
test "${name3}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[goodbye]
|
||||
Vertex: test[hello world]
|
||||
|
||||
@@ -4,6 +4,6 @@ func identity($x) {
|
||||
$x
|
||||
}
|
||||
|
||||
test identity("hey") {}
|
||||
test [identity("hey"),] {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[hey]
|
||||
|
||||
@@ -5,6 +5,6 @@ $out1 = if true {
|
||||
"world"
|
||||
}
|
||||
|
||||
test $out1 {}
|
||||
test "${out1}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[hello]
|
||||
|
||||
@@ -10,6 +10,6 @@ $fn = func($b) {
|
||||
|
||||
$out1 = $fn(true)
|
||||
|
||||
test $out1 {}
|
||||
test "${out1}" {}
|
||||
-- OUTPUT --
|
||||
Vertex: test[hello]
|
||||
|
||||
@@ -13,9 +13,9 @@ class c2() {
|
||||
|
||||
include c2 as f1
|
||||
|
||||
test $f1.z {} # yep
|
||||
#test $f1.x {} # no
|
||||
test $f1.g1.x {} # yep
|
||||
test "${f1.z}" {} # yep
|
||||
#test "${f1.x}" {} # no
|
||||
test "${f1.g1.x}" {} # yep
|
||||
|
||||
-- OUTPUT --
|
||||
Vertex: test[i am y and i am x]
|
||||
|
||||
@@ -10,9 +10,9 @@ class c2() {
|
||||
|
||||
include c2 as f1
|
||||
|
||||
test $f1.z {}
|
||||
test $f1.x {} # tricky
|
||||
test $f1.newx {}
|
||||
test "${f1.z}" {}
|
||||
test "${f1.x}" {} # tricky
|
||||
test "${f1.newx}" {}
|
||||
|
||||
-- OUTPUT --
|
||||
Vertex: test[i am x]
|
||||
|
||||
@@ -12,9 +12,9 @@ class c2() {
|
||||
|
||||
include c2 as f1
|
||||
|
||||
test $f1.z {}
|
||||
test $f1.x {} # tricky
|
||||
test $f1.newx {}
|
||||
test "${f1.z}" {}
|
||||
test "${f1.x}" {} # tricky
|
||||
test "${f1.newx}" {}
|
||||
|
||||
-- OUTPUT --
|
||||
# err: errSetScope: recursive reference while setting scope: not a dag
|
||||
|
||||
@@ -10,8 +10,8 @@ class c2() {
|
||||
|
||||
include c2 as f1
|
||||
|
||||
test $f1.z {}
|
||||
test $f1.x1 {}
|
||||
test "${f1.z}" {}
|
||||
test "${f1.x1}" {}
|
||||
|
||||
# the really tricky case
|
||||
# XXX: works atm, but not supported for now: could not set scope: variable f1.x2 not in scope
|
||||
@@ -19,7 +19,7 @@ test $f1.x1 {}
|
||||
# current child scope, which makes this variable visible. Unfortunately, it does
|
||||
# not have the correct dependency (edge) present in the Ordering system, so it
|
||||
# is flaky depending on luck of the toposort.
|
||||
#test $f1.x2 {}
|
||||
#test "${f1.x2}" {}
|
||||
|
||||
-- OUTPUT --
|
||||
Vertex: test[hey]
|
||||
|
||||
@@ -19,12 +19,12 @@ class c2() {
|
||||
|
||||
include c2 as f1
|
||||
|
||||
test $x {}
|
||||
test $f1.y {}
|
||||
test "${x}" {}
|
||||
test "${f1.y}" {}
|
||||
|
||||
# the really tricky case
|
||||
# XXX: not supported for now: could not set scope: not a dag
|
||||
#test $f1.x {}
|
||||
#test "${f1.x}" {}
|
||||
|
||||
-- OUTPUT --
|
||||
Vertex: test[i am x]
|
||||
|
||||
@@ -12,9 +12,9 @@ class c2() {
|
||||
|
||||
include c2 as f1
|
||||
|
||||
test $f1.z {}
|
||||
test $f1.x {} # tricky
|
||||
test $f1.newx {}
|
||||
test "${f1.z}" {}
|
||||
test "${f1.x}" {} # tricky
|
||||
test "${f1.newx}" {}
|
||||
|
||||
-- OUTPUT --
|
||||
# err: errSetScope: recursive reference while setting scope: not a dag
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user