113 lines
4.6 KiB
Plaintext
113 lines
4.6 KiB
Plaintext
#!/usr/bin/env nomsu -V3.6.5.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 = (new Dog {barks:2})
|
|
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 = (new Dog)
|
|
assume (%d2.barks == 0) or barf "Default initializer failed"
|
|
with {%d:new 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 = (new Corgi)
|
|
assume (%corg.barks == 0)
|
|
with {%d:new 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:new Dog {barks:2}}:
|
|
assume ((%d::bark) == "Bark! Bark!")
|
|
compile [my action %actions %body] to:
|
|
lua> ".."
|
|
local fn_name = string.as_lua_id(\%actions[1].stub)
|
|
local \%args = table.map(\%actions[1]:get_args(), function(a) return tostring(nomsu:compile(a)) end)
|
|
table.insert(\%args, \(\%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 = string.as_lua_id(alias.stub)
|
|
local \%alias_args = table.map(alias:get_args(), function(a) return tostring(nomsu:compile(a)) end)
|
|
table.insert(\%alias_args, \(\%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:
|
|
return (..)
|
|
Lua ".."
|
|
do
|
|
local class = {name=\(%classname as lua expr)}
|
|
setmetatable(class, {
|
|
__index=\(%parent as lua expr),
|
|
__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["A_"..string.as_lua_id("new "..class.name)] = class
|
|
nomsu["A_"..string.as_lua_id("new "..class.name.." 1")] = class
|
|
nomsu["A_"..string.as_lua_id(class.name)] = 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", ["length"]="__len",
|
|
["__ipairs"]="__ipairs", ["__pairs"]="__pairs",
|
|
}
|
|
for stub,metamethod in pairs(metamethod_map) do
|
|
class[metamethod] = class[string.as_lua_id(stub)]
|
|
end
|
|
end
|
|
|
|
parse [object %classname %class_body] as (..)
|
|
object %classname extends (nil) %class_body
|