Skip to content
FeynmanTech edited this page Aug 26, 2015 · 4 revisions

Getting Started

Setup

In order to run NGN, all that is needed is an environment capable of running Lua code. The main engine is written in standard Lua, with no external libraries necessary, but it can be run in any standard or non-standard Lua environment, provided the core functionality is unchanged.

Code structure

NGN programs are, by default, structured similarly to Lua programs. This can be changed via modification or extension, but the standard setup is fairly simple.

Internals

NGN is not actually a full programming language - rather, it is an engine that can be used as the core for a programming language, with a sample set of rules, or framework, built around it. The stock framework is easy to learn and fairly multipurpose, but NGN's true strength is malleability; odds are, at some point, you will want to modify its behavior to suit your needs. The engine itself is under 100 lines long, and looks like this:

    function ngn.tokenize(str)
    str = str:gsub("%[#.-#%]", ""):gsub("##.-\n", "")
    local t, r = "", ""
    while #str > 0 do
        for _, ct in ipairs(ngn.tokens) do
            local s, e = str:find(ct[1])
            if s == 1 then
                t = t .. str:sub(s, e):gsub(ct[1], ct[2])
                r = r .. ct[2]:gsub("%S?%%%d", "")
                str = str:sub(e, -1)
                break break
            end
        end
        str = str:sub(2,-1)
    end
    return t, r
end

function ngn.compile(t, lvars)
    local cs = ""
    lvars = lvars or {}
    while #t > 0 do
        for _, r in ipairs(ngn.rules) do
            local s, e = t:find(r[1])
            if s == 1 then
                local d = {t:match(r[1])}
                cs = cs .. "{<" .. _ .. ">:"
                for i, v in ipairs(d) do 
                    cs = cs .. "["
                    if v:match("%b{}") == v then
                        local comp = ngn.compile(v:sub(2,-2), lvars)
                        comp = comp
                            :gsub("%b[]",function(r)return "@OBR;"..r:sub(2,-2).."@CBR;" end)
                            :gsub("%b{}",function(r)return "@OCB;"..r:sub(2,-2).."@CCB;" end)
                        or comp
                        cs = cs .. comp
                    else
                        cs = cs .. v
                    end
                    cs = cs .. "];"
                end
                cs = cs .. "};"
                t = t:sub(e, -1)
                break break
            end
        end
        t = t:sub(2,-1)
    end
    return cs
end

function ngn.interpret(t, lvars)
    lvars = lvars or {}
    lvars.INTERP = true
    while #t > 0 do
        for _, r in ipairs(ngn.rules) do
            local s, e = t:find(r[1])
            if s == 1 then
                r[2](lvars, t:match(r[1]))
                t = t:sub(e, -1)
                break break
            end
        end
        t = t:sub(2,-1)
    end
end

function ngn.run(t, lvars)
    lvars = lvars or {}
    for b in t:gmatch("%b{};") do
        for r, a in b:gmatch("{(%b<>):(.-)};") do
            local arg = {}
            for ca in a:gmatch("(%b[]);") do
                table.insert(arg, ca:sub(2,-2))
            end
            ngn.rules[tonumber(r:sub(2,-2))][2](lvars, table.unpack(arg))
        end
    end
end

It relies on various other items in the ngn table to dictate its top-level behavior - to modify the language syntax and rules, modify or add rules to ngn.rules and, if necessary, ngn.tokens. To modify the internal behavior of the language, you can modify the engine itself. The language is similar to a car - like most languages, it looks simple from the outside but the engine itself seems extremely complicated to a novice programmer. However, also like a car engine, the code at the core of NGN is fairly simply designed, and can be easily modified by a reasonably experienced coder.

Clone this wiki locally