Skip to content

Instantly share code, notes, and snippets.

@zr-tex8r
Created June 29, 2012 14:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zr-tex8r/3018115 to your computer and use it in GitHub Desktop.
Save zr-tex8r/3018115 to your computer and use it in GitHub Desktop.
Interpreter of the programming language 'og' (originally by Google, different from 'Go')
This is an implementation of the 'Google machine' (*1), where its fancy
graphics is replaced by dull text strings.
*1 Alan Turing's 100th Birthday (in Google Doodles)
http://www.google.com/doodles/alan-turings-100th-birthday
The syntax of the language is probably easily understood by viewing the
article (*2) of the author's blog. Although it is written in Japanese
all you have to see is the graphics and the corresponding text source.
(The rule of the 'Google machine' can surely be learned by playing with
the Doodle.)
*2 "Eventually I solved the "last problem" posed by Google!"
http://d.hatena.ne.jp/zrbabbler/20120630/1341031773
CONTENT
* fizzbuzz.og - FIzzBuzz written in og (numbers are in binary)
* flipbits.og - flip the bits of the input (0110 -> 1001)
* goog.lua - the main interpreter program (in Lua)
* og.lua - the interpreter library
USAGE
Put goog.lua and og.lua in the same directory and run (for example)
lua goog.lua flipbits.og 0110
(here 'lua' is the name of Lua executable)
then the output "1001" is printed. If you run as
lua goog.lua -vvv flipbits.og 0110
then the configuration of the machine during the current run is
also displayed in detail.
(Try '--help' to know all options available.)
# 5 10 13
v_ -> @2 <- 'o <- '/ <- ': v:
'$ . <- ^_ v: @3 . . . @5
v$ v0 v1 -> @4 <- '1 . @5
v$ v0 '_ . <- v: @2 . ^/
v$ '_ <- v: @2 <- '1 v1 ^/
'_ v_ . <- '0 . . <- ^/ ': v:
v: <- @2 . -> -> '+ -> ^/ @2 @6
<- <- '0 <- '% v/ -> @2
v$ . -> '$ @4 -> @4
# 5 10 13
'_ -> '$ v% <- @2 . @7
v0 v: v1 -> @4 -> @3 ^$ . . . . @5
v0 v: '0 . . ^0 . . . . . . ^$
v0 <- <- '1 . . <- v% @2 . . . ^$
v0 '_ <- '0 <- '% v% @6 . . . . ^$
'1 v/ -> @2 . . @5 . . . . . ^$
# 5 10 13
v/ -> . vn <- @5 'F -> 'i -> v_ . ^$
v/ . v_ 'o . -> ^$ @2 . . @8 . ^$
v/ v_ 'z -> 'z -> 'B -> 'u -> @9 . ^$
v/ 'z -> 'z -> '$ . . . . . v$ ^$
-> vb . ve . vh . vk <- v/ . v$ ^$
v/ 'c vc 'f vf 'i vi 'l vl @9 . v$ ^$
v/ v/ . . . . . . <- @8 . v$ ^$
v/ v$ -> @2 . . . . . . . v$ ^$
v/ 'F -> 'i -> 'z -> 'z -> '$ . v$ ^$
-> vd . vi . . . . <- v/ . v$ ^$
v/ 'e ve 'j vj . . . . @9 . v$ ^$
v/ v/ . . . . . . <- @8 . v$ ^$
v/ v$ -> @2 . . . . . . . v$ ^$
v/ 'B -> 'u -> 'z -> 'z -> '$ . v$ ^$
-> va . vc . vf . vg <- v/ . v$ ^$
v/ 'b vb 'd vd 'g vg 'h vh @9 . v$ ^$
v/ . . . . . . . <- v/ . v$ ^$
-> vj . vl . vm . 'a <- v/ . v$ ^$
v/ 'k vk 'm vm 'n vn . <- @9 . v$ ^$
v/ . . . . . . . <- @9 . v$ ^$
# 5 10 13
v/ . . v: <- @2 '+ v+ . . v% @8 ^$
<- v: @2 . . . ^_ <- ^% @3 v% . ^$
# 5 10 13
v% v_ <- @3 '1 . . . v1 @7 . v% ^$
v% '+ <- v0 ^$ -> @2 '0 -> ^: v_ v% ^$
v% . '$ . . v$ -> ^$ @2 ^: @8 v% ^$
v% <- @2 . @4 . . . <- ^: @2 @7 ^$
v: v+ -> @3 ^_ . . . @4 . . . ^$
v: '_ <- v0 v: -> @2 . ^_ . . . ^$
v: . . v0 v+ -> @2 -> ^_ . . . ^$
v: v_ . v0 '_ <- . ^1 ^_ -> @9 . ^$
v: v_ . . v: -> @2 . ^_ . . . ^$
v: v_ . . v+ -> @2 -> ^_ . . . ^$
v: v_ '+ v+ '_ <- . ^0 -> @8 . . ^$
v: v: ^_ <- @3 '_ v_ . . -> ^$ @2 @8
v: . . . . ^+ <- ^% @3 . . . ^+
v: . '_ ^_ . ^$ -> @2 . . . . ^+
v/ v+ -> @3 . . . . . . . . ^+
v/ . . . ^+
# 5 10 13
<- v% '_ @3 '_ -> '_ v_ . . v$
. '_ . -> ^/ @2 . -> ^$ @2 '_
v0 . v1 v_ -> @5
'1 v1 '0 ^0 ^1 .
. . . . ^1 .
--
-- goog.lua
--
prog_name = "goog"
version = "0.3"
mod_date = "2012/07/02"
author = "ZR(T.Yato)"
package.path = arg[0]:gsub("%w+%.lua$", "?.lua;")..package.path
og = require 'og'
input, source, verbose, quiet = nil
vwidth, vheight, vtop, limit = nil
detail = nil
function show_usage()
print(("This is %s, v%s<%s> by %s")
:format(prog_name, version, mod_date, author))
print(([=[
Usage: %s [-e] [-f] [-v] [-q] [-w<size>] [<source> [<input>]]
-e source is given as string (not as file)
-f input is given as file (not as string)
-v enable debug print (-vv, -vvv for more info)
-q suppress warning
-w[<w>][x[<h>][+[<t>]]] tell window size (for debug-print)
<source> source (string or file)
<input> input to the machine (string or file)
]=]):format(prog_name))
os.exit()
end
function main()
read_option()
og.verbose_level(verbose)
og.view_size(vheight, vwidth, vtop)
if limit then og.limit(limit) end
local result = og.run(source, input)
if result then
if detail then print(("Output=(%s)"):format(result))
else io.stdout:write(result)
end
else warning("machine did not halt")
end
end
function read_option()
local file_input = false
local file_source = true
verbose = 0; quiet = false
if not arg[1] then
show_usage()
end
while arg[1] and arg[1]:sub(1, 1) == '-' and arg[1] ~= '-' do
local opt = table.remove(arg, 1)
if opt == '-h' or opt == '-help' or opt == '--help' then
show_usage()
elseif opt == '-f' then
file_input = true
elseif opt == '-e' then
file_source = false
elseif opt == '-q' then
quiet = true
elseif opt == '-d' then
detail = true
elseif opt:find("^-v+$") then
verbose = opt:len() - 1
elseif opt:sub(1, 2) == "-l" then
local oarg = opt:sub(3)
if oarg == "" then oarg = table.remove(arg, 1) or "" end
limit = tonumber(oarg)
if not limit then
error_exit("illegal argument for -l", oarg)
end
elseif opt:sub(1, 2) == "-w" then
local oarg = opt:sub(3)
if oarg == "" then oarg = table.remove(arg, 1) or "" end
local r1 = { oarg:find("^(%d*)$") }
local r2 = { oarg:find("^(%d*)x(%d*)$") }
local r3 = { oarg:find("^(%d*)x(%d*)%+(%d*)$") }
if r1[1] then
vwidth = tonumber(r1[3])
elseif r2[1] then
vwidth, vheight = tonumber(r2[3]), tonumber(r2[4])
elseif r3[1] then
vwidth, vheight = tonumber(r3[3]), tonumber(r3[4])
vtop = tonumber(r3[5])
else
error_exit("illegal argument for -w", oarg)
end
else
error_exit("unknown option", opt)
end
end
input, source = file_input, file_source
if #arg > 2 then
error_exit("too many arguments given")
end
if file_source then source = read_whole(arg[1])
else source = arg[1] or ""
end
if file_input then input = read_whole(arg[2])
else input = arg[2] or ""
end
if source:find("^%s*$") then
warning("program source is empty")
end
end
function read_whole(filename)
local file = io.stdin
if filename and filename ~= "" and filename ~= "-" then
file = io.open(filename, "r")
end
if not file then
error_exit("cannot open for input", filename)
end
local data = assert(file:read("*a"))
file:close()
return data
end
function error_exit(...)
local msg = table.concat({ prog_name, ... }, ": ").."\n"
io.stderr:write(msg)
os.exit(-1)
end
function warning(...)
if quiet then return end
local msg = table.concat({ prog_name, "warning", ... }, ": ").."\n"
io.stderr:write(msg)
end
main()
-- EOF
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment