119 lines
4.8 KiB
Plaintext
119 lines
4.8 KiB
Plaintext
#!/usr/bin/env nomsu -V4.8.8.6
|
|
#
|
|
This file contains the implementation of an Object-Oriented programming system.
|
|
|
|
test:
|
|
object (Dog):
|
|
(Dog).genus = "Canus"
|
|
my action [set up]: %me.barks or= 0
|
|
my action [bark, woof]:
|
|
%barks = ("Bark!" for % in 1 to %me.barks)
|
|
return (%barks::joined with " ")
|
|
|
|
my action [get pissed off]: %me.barks += 1
|
|
|
|
%d = (Dog {barks:2})
|
|
assume (type of %d) == "Dog"
|
|
assume (%d is a "Dog")
|
|
assume %d.barks == 2
|
|
assume ((%d::bark) == "Bark! Bark!")
|
|
assume ((%d::woof) == "Bark! Bark!")
|
|
%d::get pissed off
|
|
assume (%d.barks == 3)
|
|
assume ((%d::bark) == "Bark! Bark! Bark!")
|
|
assume (%d.genus == "Canus")
|
|
assume ("\(%d.class)" == "Dog")
|
|
assume (%d.genus == "Canus")
|
|
assume (%d.barks == 3)
|
|
%d2 = (Dog {})
|
|
assume (%d2.barks == 0) or barf "Default initializer failed"
|
|
with {%d:Dog {barks:1}}:
|
|
assume ((%d::bark) == "Bark!")
|
|
object (Corgi) extends (Dog):
|
|
my action [sploot] "splooted"
|
|
my action [bark, woof]:
|
|
%barks = ("Yip!" for % in 1 to %me.barks)
|
|
return (%barks::joined with " ")
|
|
|
|
%corg = (Corgi {})
|
|
assume (%corg.barks == 0)
|
|
with {%d:Corgi {barks:1}}:
|
|
assume ((%d::sploot) == "splooted") or barf "subclass method failed"
|
|
assume ((%d::bark) == "Yip!") or barf "inheritance failed"
|
|
assume ((%d::woof) == "Yip!")
|
|
|
|
with {%d:Dog {barks:2}}:
|
|
assume ((%d::bark) == "Bark! Bark!")
|
|
compile [my action %actions %body] to:
|
|
lua> "\
|
|
..local fn_name = \%actions[1].stub:as_lua_id()
|
|
local \%args = table.map(\%actions[1]:get_args(), function(a) return tostring(nomsu:compile(a)) end)
|
|
table.insert(\%args, 1, \(\%me as lua id))
|
|
local lua = LuaCode(tree.source, "class.", fn_name, " = ", \(..)
|
|
compile as (%args -> %body)
|
|
..)
|
|
for i=2,#\%actions do
|
|
local alias = \%actions[i]
|
|
local alias_name = alias.stub:as_lua_id()
|
|
local \%alias_args = table.map(alias:get_args(), function(a) return tostring(nomsu:compile(a)) end)
|
|
table.insert(\%alias_args, 1, \(\%me as lua id))
|
|
lua:append("\\nclass.", alias_name, " = ")
|
|
if utils.equivalent(\%args, \%alias_args) then
|
|
lua:append("class.", fn_name)
|
|
else
|
|
lua:append("function(")
|
|
lua:concat_append(\%alias_args, ", ")
|
|
lua:append(")\\n return class.", fn_name, "(")
|
|
lua:concat_append(\%args, ", ")
|
|
lua:append(")\\nend")
|
|
end
|
|
end
|
|
return lua"
|
|
|
|
compile [object %classname extends %parent %class_body] to:
|
|
unless (%classname.type == "Action"):
|
|
compile error at %classname "Expected this to be an action, not a \(%classname.type)"
|
|
for % in %classname:
|
|
unless (% is text):
|
|
compile error at % "Class names should not have arguments."
|
|
return (..)
|
|
Lua "\
|
|
..do
|
|
local class = {name=\(quote %classname.stub)}
|
|
setmetatable(class, {
|
|
__index=\(%parent as lua expr),
|
|
__type=class.name,
|
|
__tostring=function(cls) return cls.name end,
|
|
__call=function(cls, inst)
|
|
inst = setmetatable(inst or {}, cls)
|
|
if inst.set_up then
|
|
inst:set_up()
|
|
end
|
|
return inst
|
|
end,
|
|
})
|
|
nomsu.environment[(class.name.." 1"):as_lua_id()] = class
|
|
nomsu.environment[class.name:as_lua_id()] = function() return class end
|
|
class.__index = class
|
|
class.class = class
|
|
class.__tostring = function(inst)
|
|
return inst.name..getmetatable(_Dict{}).__tostring(inst)
|
|
end
|
|
\(%class_body as lua statements)
|
|
local metamethod_map = {["as text"]="__tostring", ["clean up"]="__gc",
|
|
["+ 1"]="__add", ["- 1"]="__sub", ["* 1"]="__mul", ["/ 1"]="__div",
|
|
["-"]="__unm", ["// 1"]="__idiv", ["mod 1"]="__mod", ["^ 1"]="__pow",
|
|
["& 1"]="__band", ["| 1"]="__bor", ["~ 1"]="__bxor", ["~"]="__bnot",
|
|
["<< 1"]="__bshl", [">> 1"]="__bshr", ["== 1"]="__eq", ["< 1"]="__lt",
|
|
["<= 1"]="__le", ["set 1 = 2"]="__newindex", ["size"]="__len",
|
|
["iterate"]="__ipairs", ["iterate all"]="__pairs",
|
|
}
|
|
for stub,metamethod in pairs(metamethod_map) do
|
|
class[metamethod] = class[stub:as_lua_id()]
|
|
end
|
|
end"
|
|
|
|
parse [object %classname %class_body] as (..)
|
|
object %classname extends (nil) %class_body
|
|
|