The goal for Petal is that types and functions should be first-class. However, I’m not sure this is doable.
Specifically, we want:
We should be able to specify some required interface for the type to conform to and use everything in that interface seamlessly. Or perhaps the compiler should do it for us and we can optionally be more explicit.
We want to read data about things defined in our program:
We should be able to alter the flow of execution easily according to data that we’ve read. This should include things like calling a function only if the type defines it, accessing a field only if it’s visible, that sort of thing. This should type-check properly and not cause compilation errors.
The moral equivalent of:
if hasattr(obj, 'foo', Int -> Int):
a: Int = obj.foo(10)
We want to be able to produce new declarations, blocks of statements, or even expressions. We want to do this easily when we have inputs that are strings, numbers, other user-defined data structures, types, etc.
Jsonizable ClassType ty -> ClassType {
let outtype = ty:clone.
outtype.base = ty.
let fn = Method "jsonize" (-> Json).
fn:body += <! let Json js! !>.
for field in outtype:fields {
# Pretend we defined :jsonize UFCS-able funcs for builtins
fn:body += <! js[${field:name}] = ${field:get this}:jsonize. !>.
}
fn:body += <! return js. !>.
outtype.members += fn.
return outtype.
}
class Foo {
string a.
int b.
}
main {
let (Jsonizable Foo) f!
# or:
# let JFoo = Jsonizable Foo.
# let JFoo f!
f:a = "hello world".
f:b = 10.
println f:jsonize:str.
}
This would output:
{"a":"hello world","b":10}
<! ... !>
stuff?
decl+
, decl_or_statement+
, attr
,
expr
?${}
syntax