[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: [ANN] Cratera Compiler v1.0.0
- From: "Soni \"They/Them\" L." <fakedme@...>
- Date: Thu, 1 Aug 2019 10:30:00 -0300
On 2019-07-31 6:09 p.m., Egor Skriptunoff wrote:
On Wed, Jul 31, 2019 at 7:07 AM Soni "They/Them" L. wrote:
Cratera is a language very similar to Lua, and as such most of the
Lua
manual applies to it. Additionally, it supports the following syntax
sugar, called "traits":
mytable:[mytrait].myfunction(myargument)
which is equivalent to:
mytable[mytrait].myfunction(mytable, myargument)
1)
Is this feature really needed?
Please show an example.
This is heavily inspired by Rust traits. In Rust, you can do something like:
fn main() {
let v = <Vec<_> as From<&str>>::from("hello, world!");
println!("{:?}", v);
}
(However, in this case you're using "<Type as Trait>::function()". I
don't know why Rust doesn't support "<binding as Trait>.method()" but I
had to adapt this whole thing.)
You can also call methods from traits using the object. I took these
ideas and adapted them for a dynamic programming language like Lua.
It's just a different way of doing OOP. Since Lua prides itself on
having many ways of doing OOP as long as you implement them yourself
(you can have classes in Lua, but you can also have prototype-based OOP,
but you can also have even other forms of OOP. some of those are more or
less efficient than others.), I decided to implement trait-based OOP as
efficiently as I knew how - with a language extension.
You can see a small example in tests.cratera (see below). However, keep
in mind it was my first cratera example and I hadn't fully worked out
how you should be doing things in cratera - I wouldn't do it exactly
like that nowadays. But it does capture the basic idea.
--------
-- example from tests.cratera
entity = {}
inventory = {get=false, set=false, size=false}
inventory.new=function(size)
local t = {size=function() return size end}
function t.set(e, i, o)
if i <= 0 or i > e:[inventory].size() then error() end
e[inventory][i] = o
end
function t.get(e, i)
if i <= 0 or i > e:[inventory].size() then error() end
return e[inventory][i]
end
return t
end
inventory.of=function(e) -- helper for passing standalone inventories around
return {get=function(...)return e:[inventory].get(...)end,
set=function(...)return e:[inventory].set(...)end,
size=function(...)return e:[inventory].size(...)end}
end
entity[inventory] = inventory.new(5)
entity:[inventory].set(1, "Hello World!")
print(entity:[inventory].get(1))
for i=1, entity:[inventory].size() do
print(i, entity:[inventory].get(i))
end
local myinv = inventory.of(entity)
for i=1, myinv.size() do
print("wrapped", i, myinv.get(i))
end
--------
2)
Am I able to invoke a method by its name from a variable in Cratera?
local methodname = "close"
file:[methodname]()
No. While that was implemented in the Cratera patchset, it's not
implemented in Cratera Compiler. Cratera is implemented with a function
by Cratera Compiler, and to support this syntax I'd need another
function. Given the usefulness of this feature for Cratera programs in
general (read: nonexistent), I decided against implementing it. It's
recommended that you wrap the Lua stdlib to use Cratera OOP if you're
writing a Cratera program. Then you'll be able to use:
file:[io].read()
file:[close].close()
3)
Cratera's feature could be generalized further.
The following two simple rules look like a natural extension to Lua
syntax:
- There could be multiple colons in a chain
- Each colon means "use current value as extra argument"
Examples:
a:b[c].f(x) -> a.b[c].f(a, x)
a.b:[c].f(x) -> a.b[c].f( a.b, x)
a.b[c]:f(x) -> a.b[c].f( a.b[c], x)
a:b[c]:f(x) -> a.b[c].f(a, a.b[c], x)
a.b[c].f:(x) -> a.b[c].f( a.b[c].f, x)
a:b:[c]:f:(x) -> a.b[c].f(a, a.b, a.b[c], a.b[c].f, x)
c:() -> c(c)
It's not a monkey smile in the last line, variable "c" contains a
"callable object"
Lua has a nesting limit of 200 or so. a:[b].c() is converted into
(CRATERA_FN)(a, b, "c"), which increases the nesting of a and b by one.
A normal Lua function chain can go on forever, but Cratera is limited to
less than 200 occurrences of traits per statement. If you could use
arbitrarily many colons in a chain, that limit would be even lower even
quicker.