lua-users home
lua-l archive

Re: Some syntax troubles

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


> -- Syntax is a bit more complicated that what you exacly want
> local Foo = in_context_of(my_dsl)
> {
> ["Alpha"] = { 'op1', "a", 'op2', "b" };
> ["Beta"] = { 'op2', "a", 'op1', "b", 'op3', "c" };
> };
Hey, this is an interesting idea for implementation of some kind of
virtual machine-interpreted DSL:
Silly example:
-- Should print 3.
interprete(make_vm()) 'add' '1 '2' 'prn'
Code follows.
Alexander.
=======
assert_is_function = function(val, msg)
 assert(type(val) == "function", msg)
 return val
end
assert_is_table = function(val, msg)
 assert(type(val) == "table", msg)
 return val
end
assert_is_string = function(val, msg)
 assert(type(val) == "string", msg)
 return val
end
in_context_of = function(t)
 assert_is_table(t)
 return function(func)
 assert_is_function(func)
 -- TODO: Get the original environment of the function!
 setfenv(func, t)
 return func(), setfenv(func, _G) -- Assuming setfenv returns nil.
 end
end
local make_nary = function(num)
 assert(num >= 0)
 local wrapper = function(func)
 assert_is_function(func)
 -- Instruction parameter is for error reporting only.
 -- TODO: These should be implemented more effectively,
 -- removing table creation and function creation
 -- on each operand call.
 local brancher = function(callback, instruction_name)
 assert_is_function(callback)
 assert_is_string(instruction_name)
 if num == 0 then
 func()
 return callback
 else
 local n = num
 local operands = { }
 local operand_collector
 operand_collector = function(operand)
 assert(operand, instruction_name .. " : " .. num .. "
operands required.")
 table.insert(operands, operand)
 n = n - 1
 if n > 0 then
 return operand_collector
 else
 func(unpack(operands))
 return callback
 end
 end
 return operand_collector
 end
 end
 return brancher
 end
 return wrapper
end
interprete = function(vm_instructions)
 assert(vm_instructions)
 local interpreter
 interpreter = function(op)
 assert(op)
 local handler = vm_instructions[op]
 assert_is_function(handler, "Unknown instruction, " .. op)
 return handler(interpreter, op)
 end
 return interpreter
end
interpreter_util =
{
 -- TODO: Would benefit from optimized version of each!
 nullary = make_nary(0);
 unary = make_nary(1);
 binary = make_nary(2);
 nary = make_nary;
}
-- All VM API should be mentioned here due to in_context_of's setfenv call.
-- If this is not what you want, you can move implementation of instruction
-- handling functions outside of the instruction table declaration.
-- Or just remove that in_context_of call.
local my_vm_api =
{
 print = print;
}
local make_vm_1 = function()
 local vm = my_vm_api
 return in_context_of(interpreter_util) (function()
 return
 {
 op0 = nullary (function() vm.print("op0") end);
 op1 = unary (function(var) vm.print("op1", var) end);
 op2 = binary (function(var1, var2) vm.print("op2", var1, var2) end);
 op3 = nary(3) (function(var1, var2, var3) vm.print("op3", var1,
var2, var3) end);
 }
 end)
end
-- Silly example for VM with state.
local make_vm_2 = function()
 local op1 = 0
 local op2 = 0
 local result = 0
 local vm = my_vm_api
 return in_context_of(interpreter_util) (function()
 return
 {
 add = binary (function(var1, var2) result = var1 + var2 end);
 prn = nullary (function() vm.print(result) end);
 }
 end)
end
interprete(make_vm_1()) 'op0' 'op1' 'a' 'op0' 'op3' 'b' 'c' 'd' 'op2' 'e' 'f'
-- TODO: Handle "hanging" instructions with not enough parameters at
the end of the stream.
-- like "interprete(make_my_vm()) 'inc'". For example, it can
be done by passing
-- special 'end' opcode at the end of the stream.
interprete(make_vm_2()) 'prn' 'add' '1' '2' 'prn'
-- Note states of VMs are separate
interprete(make_vm_2()) 'prn'

AltStyle によって変換されたページ (->オリジナル) /