Skip to content

Commit

Permalink
added :r command to REPL, removed global arg from define,
Browse files Browse the repository at this point in the history
  • Loading branch information
zot committed Apr 11, 2012
1 parent d82d7e2 commit c90d5ea
Show file tree
Hide file tree
Showing 13 changed files with 185 additions and 110 deletions.
20 changes: 11 additions & 9 deletions TODO.md
@@ -1,14 +1,7 @@
[Main](README.html) [Reference](REFERENCE.html) [Status](TODO.html) [Source](http://github.com/zot/lazp) [REPL](lazp.html) [Standard functinos](std.laz)
# TODO
* Run Lazp in sandbox
* lazp.cs, std.laz, prim.cs run in a sandbox
* in browser, use an iframe with ifr.contentWindow.eval() to communicate
* iframe.contentWindow holds globals
* allow user to show or hide iframe (it's where SVG etc can be)
* in node, use VM.createContext and VM.runInContext to communicate
* context holds globals
* repl uses sandbox
* allows for reloading, etc.
* disallow redefinition
* :r resets env in REPL
* indentation tweak
* indent line creates a nested expression
* throw error on undeclared variables -- require quotes for strings
Expand Down Expand Up @@ -63,6 +56,15 @@
* [optimistic evaluation](http://research.microsoft.com/en-us/um/people/simonpj/Papers/optimistic/index.htm)?

#DONE
* Run Lazp in sandbox
* lazp.cs, std.laz, prim.cs run in a sandbox
* in browser, use an iframe with ifr.contentWindow.eval() to communicate
* iframe.contentWindow holds globals
* allow user to show or hide iframe (it's where SVG etc can be)
* in node, use VM.createContext and VM.runInContext to communicate
* context holds globals
* repl uses sandbox
* allows for reloading, etc.
* pretty print code
* runRepl file should compile the file, eval it, and then stay in the REPL
* get ! working on browser
Expand Down
15 changes: 13 additions & 2 deletions browserRepl.cs
Expand Up @@ -17,6 +17,7 @@
if ast.lazpName? then defs.innerHTML += "#{markupDef(src, ast)}<br>"
else if result then output.innerHTML += "<b>> #{lastLine} \u2192</b>\n #{ReplCore.getType result}: #{Pretty.print result}\n"
ReplCore.processResult result
ReplCore.setResetFunc clearEnv
input = inputField
input.onkeypress = (e)->
if (e.charCode || e.keyCode || e.which) == 13
Expand All @@ -32,9 +33,18 @@ ReplCore.processResult result
ReplCore.help()
o.innerHTML += '\n'

clearEnv = (clearEnv)->
document.getElementById('defs').innerHTML = ""
env = document.getElementById('env')
document.body.removeChild(env)
newEnv = document.createElement('iframe')
newEnv.id = 'env'
newEnv.setAttribute("style", "display: none")
newEnv.setAttribute("onload", "Repl.useIframe(this)")
document.body.appendChild(newEnv)

useIframe = (envFr)->
if (envFr)
if (envFr.getAttribute('duh')) then alert(envFr.getAttribute('duh'))
root.envFrame = envFrame = envFr
env = envFrame.contentWindow
env[i] = v for i, v of lazpFuncs
Expand All @@ -55,7 +65,7 @@ ReplCore.processResult result
if src.match /^\s*#/ then src
if (match = src.match Lazp.linePat)
[matched, leading, name, defType] = match
"<b>#{name}</b> #{defType} #{src.substring(matched.length)}"
"<div><b>#{name}</b> #{defType} #{src.substring(matched.length)}</div>"
else line

markupLines = (lines)-> lines.split('\n').map(markupDef).join('<br>')
Expand Down Expand Up @@ -84,3 +94,4 @@ ReplCore.processResult result
root.handleFiles = handleFiles
root.useIframe = useIframe
root.reloadEnv = reloadEnv
root.clearEnv = clearEnv
20 changes: 17 additions & 3 deletions browserRepl.js
@@ -1,5 +1,5 @@
(function() {
var Pretty, clearOutput, envFrame, handleFiles, init, input, lastLine, markupDef, markupLines, processResult, reloadEnv, root, useIframe, write;
var Pretty, clearEnv, clearOutput, envFrame, handleFiles, init, input, lastLine, markupDef, markupLines, processResult, reloadEnv, root, useIframe, write;

if ((typeof window !== "undefined" && window !== null) && (!(typeof global !== "undefined" && global !== null) || global === window)) {
window.global = window;
Expand Down Expand Up @@ -35,6 +35,7 @@
}
return ReplCore.processResult(result);
});
ReplCore.setResetFunc(clearEnv);
input = inputField;
input.onkeypress = function onkeypress(e) {
if ((e.charCode || e.keyCode || e.which) === 13) {
Expand All @@ -57,10 +58,21 @@
return o.innerHTML += '\n';
};

clearEnv = function clearEnv(clearEnv) {
var env, newEnv;
document.getElementById('defs').innerHTML = "";
env = document.getElementById('env');
document.body.removeChild(env);
newEnv = document.createElement('iframe');
newEnv.id = 'env';
newEnv.setAttribute("style", "display: none");
newEnv.setAttribute("onload", "Repl.useIframe(this)");
return document.body.appendChild(newEnv);
};

useIframe = function useIframe(envFr) {
var env, i, v, _ref;
if (envFr) {
if (envFr.getAttribute('duh')) alert(envFr.getAttribute('duh'));
root.envFrame = envFrame = envFr;
env = envFrame.contentWindow;
for (i in lazpFuncs) {
Expand All @@ -87,7 +99,7 @@
if (src.match(/^\s*#/)) src;
if ((match = src.match(Lazp.linePat))) {
matched = match[0], leading = match[1], name = match[2], defType = match[3];
return "<b>" + name + "</b> " + defType + " " + (src.substring(matched.length));
return "<div><b>" + name + "</b> " + defType + " " + (src.substring(matched.length)) + "</div>";
} else {
return line;
}
Expand Down Expand Up @@ -133,4 +145,6 @@

root.reloadEnv = reloadEnv;

root.clearEnv = clearEnv;

}).call(this);
25 changes: 13 additions & 12 deletions lazp.cs
Expand Up @@ -80,11 +80,9 @@

evalFunc = eval

define = (name, gl, func) ->
define = (name, func) ->
nm = nameSub(name)
#console.log("DEFINE: #{name} (#{nm}), CTX: #{ctx}, FUNCS: #{lazpFuncs}, GLOBAL: #{gl}")
#ctx[nm] = lazpFuncs[nm] = global[nm] = -> func
ctx[nm] = gl.lazpFuncs[nm] = gl[nm] = -> func
ctx[nm] = ctx.lazpFuncs[nm] = -> func
func.lazpName = name
func

Expand All @@ -103,15 +101,15 @@

evalCompiledAst = (ast)-> if ast.lits.length then evalFunc("(function(__lits){\nreturn #{ast.src}})")(ast.lits) else evalFunc(ast.src)

define 'eval', global, (ast)-> evalCompiledAst(dgen(ast()))
define 'eval', (ast)-> evalCompiledAst(dgen(ast()))

define 'lit', global, (_x)->setType ((_f)-> _f()(_x)), 'lit'
define 'lit', (_x)->setType ((_f)-> _f()(_x)), 'lit'

define 'ref', global, (_x)->setType ((_f)-> _f()(_x)), 'ref'
define 'ref', (_x)->setType ((_f)-> _f()(_x)), 'ref'

define 'lambda', global, (_v)-> (_f)-> setType ((_g)-> _g()(_v)(_f)), 'lambda'
define 'lambda', (_v)-> (_f)-> setType ((_g)-> _g()(_v)(_f)), 'lambda'

define 'apply', global, (_func)-> (_arg)-> setType ((_f)-> _f()(_func)(_arg)), 'apply'
define 'apply', (_func)-> (_arg)-> setType ((_f)-> _f()(_func)(_arg)), 'apply'

getType = (f)->
t = typeof f
Expand Down Expand Up @@ -209,12 +207,12 @@ class Code
else if code.subfuncs.length then ast.src = """
(function(){#{if tokenDef? and tokenDef != '=' then "root.tokenDefs.push('#{name}', '#{tokenDef}')\n" else ''}
#{code.subfuncs}
return #{if name? then "define('#{name}', global, #{code.main})" else code.main}
return #{if name? then "define('#{name}', #{code.main})" else code.main}
})()
"""
else ast.src = if name? then """
(function(){#{if tokenDef? and tokenDef != '=' then "root.tokenDefs.push('#{name}', '#{tokenDef}');\n" else ''}
return define('#{name}', global, #{code.main});
return define('#{name}', #{code.main});
})()
""" else "(#{code.main})"
ast.globals = code.global
Expand Down Expand Up @@ -301,14 +299,17 @@ class Code
if nm
astsByName[nm[0]] = 1
if defType && defType != '=' then defineToken(nm[0], defType)
ifParsed (parseApply (prefix nm, rest1), Nil), (ast, rest)->
pfx = (prefix nm, rest1)
ifParsed (parseApply pfx, Nil), (ast, rest)->
bod = ast
if nm.length > 1 then bod = getNthBody(ast, nm.length)
if getAstType(bod) == 'lambda'
bod.exprType = nm[0]
ast.exprDataType = nm[0]
nameAst(nm[0], ast)
if nm.length == 1 then nameAst(nm[0], ast)
ast.lazpPrefixSrcLen = pfx.length
ast.lazpPrefixCount = nm.length
genCode ast, nm[0], globals, defType, rest, parseOnly
else ifParsed (parseApply rest1, Nil), (ast, rest)->
genCode ast, null, globals, null, rest, parseOnly
Expand Down
15 changes: 1 addition & 14 deletions lazp.html
Expand Up @@ -25,19 +25,6 @@
Repl.init(input, output, defs)
clearOutput()
}
function clearEnv() {
document.getElementById('defs').innerHTML = ""
env = document.getElementById('env')
document.body.removeChild(env)
var i = Number(env.getAttribute('duh'))
newEnv = document.createElement('iframe')
newEnv.id = 'env'
newEnv.setAttribute("style", "display: none")
newEnv.setAttribute("onload", "Repl.useIframe(this)")
newEnv.setAttribute("duh", String(i + 1))
document.body.appendChild(newEnv)
// Repl.useIframe(newEnv)
}
function changeStdLinks() {
changeStdLink('stdDefsLink1')
changeStdLink('stdDefsLink2')
Expand Down Expand Up @@ -89,7 +76,7 @@
</div>
</td>
</tr>
<tr style="height: 0"><td colspan="2" class="cell"><table style="width: 100%; white-space: nowrap"><tr><td style="width: 100%"><input id="input" type="text" style="width: 100%; margin: 0"></td><td style="width: 0"><div>Load file: <input type="file" onchange="Repl.handleFiles(this)"></input><button onclick="clearEnv()">Clear</button></td></tr></table></td></tr>
<tr style="height: 0"><td colspan="2" class="cell"><table style="width: 100%; white-space: nowrap"><tr><td style="width: 100%"><input id="input" type="text" style="width: 100%; margin: 0"></td><td style="width: 0"><div>Load file: <input type="file" onchange="Repl.handleFiles(this)"></input><button onclick="Repl.clearEnv()">Clear</button></td></tr></table></td></tr>
</table>
<iframe duh="1" id="env" style="display: none" onload="Repl.useIframe(this)"></iframe>
</body>
Expand Down
25 changes: 14 additions & 11 deletions lazp.js
Expand Up @@ -113,10 +113,10 @@ misrepresented as being the original software.

evalFunc = eval;

define = function define(name, gl, func) {
define = function define(name, func) {
var nm;
nm = nameSub(name);
ctx[nm] = gl.lazpFuncs[nm] = gl[nm] = function() {
ctx[nm] = ctx.lazpFuncs[nm] = function() {
return func;
};
func.lazpName = name;
Expand Down Expand Up @@ -151,31 +151,31 @@ misrepresented as being the original software.
}
};

define('eval', global, function(ast) {
define('eval', function(ast) {
return evalCompiledAst(dgen(ast()));
});

define('lit', global, function(_x) {
define('lit', function(_x) {
return setType((function(_f) {
return _f()(_x);
}), 'lit');
});

define('ref', global, function(_x) {
define('ref', function(_x) {
return setType((function(_f) {
return _f()(_x);
}), 'ref');
});

define('lambda', global, function(_v) {
define('lambda', function(_v) {
return function(_f) {
return setType((function(_g) {
return _g()(_v)(_f);
}), 'lambda');
};
});

define('apply', global, function(_func) {
define('apply', function(_func) {
return function(_arg) {
return setType((function(_f) {
return _f()(_func)(_arg);
Expand Down Expand Up @@ -434,9 +434,9 @@ misrepresented as being the original software.
if (code.err !== '') {
ast.err = code.err;
} else if (code.subfuncs.length) {
ast.src = "(function(){" + ((tokenDef != null) && tokenDef !== '=' ? "root.tokenDefs.push('" + name + "', '" + tokenDef + "')\n" : '') + "\n " + code.subfuncs + "\n return " + (name != null ? "define('" + name + "', global, " + code.main + ")" : code.main) + "\n})()";
ast.src = "(function(){" + ((tokenDef != null) && tokenDef !== '=' ? "root.tokenDefs.push('" + name + "', '" + tokenDef + "')\n" : '') + "\n " + code.subfuncs + "\n return " + (name != null ? "define('" + name + "', " + code.main + ")" : code.main) + "\n})()";
} else {
ast.src = name != null ? "(function(){" + ((tokenDef != null) && tokenDef !== '=' ? "root.tokenDefs.push('" + name + "', '" + tokenDef + "');\n" : '') + "\nreturn define('" + name + "', global, " + code.main + ");\n})()" : "(" + code.main + ")";
ast.src = name != null ? "(function(){" + ((tokenDef != null) && tokenDef !== '=' ? "root.tokenDefs.push('" + name + "', '" + tokenDef + "');\n" : '') + "\nreturn define('" + name + "', " + code.main + ");\n})()" : "(" + code.main + ")";
}
ast.globals = code.global;
return ast;
Expand Down Expand Up @@ -571,15 +571,16 @@ misrepresented as being the original software.
};

compileNext = function compileNext(line, globals, parseOnly) {
var def, defType, leading, matched, name, nm, rest1;
var def, defType, leading, matched, name, nm, pfx, rest1;
if ((def = line.match(linePat)) && def[1].length !== line.length) {
matched = def[0], leading = def[1], name = def[2], defType = def[3];
rest1 = line.substring((defType ? matched : leading).length);
nm = defType ? name.trim().split(/\s+/) : null;
if (nm) {
astsByName[nm[0]] = 1;
if (defType && defType !== '=') defineToken(nm[0], defType);
return ifParsed(parseApply(prefix(nm, rest1), Nil), function(ast, rest) {
pfx = prefix(nm, rest1);
return ifParsed(parseApply(pfx, Nil), function(ast, rest) {
var bod;
bod = ast;
if (nm.length > 1) bod = getNthBody(ast, nm.length);
Expand All @@ -589,6 +590,8 @@ misrepresented as being the original software.
}
nameAst(nm[0], ast);
if (nm.length === 1) nameAst(nm[0], ast);
ast.lazpPrefixSrcLen = pfx.length;
ast.lazpPrefixCount = nm.length;
return genCode(ast, nm[0], globals, defType, rest, parseOnly);
});
} else {
Expand Down
44 changes: 24 additions & 20 deletions prim.cs
Expand Up @@ -23,22 +23,26 @@
define = Lazp.define
getType = Lazp.getType

define 'is', global, (value)-> (type)-> if value()?.type == type().dataType then `_true()` else `_false()`
define 'eq', global, (a)-> (b)-> if a() == b() then `_true()` else` _false()`
define 'withType', global, (value)->(t)->(f)-> if type = getType(value()) then t()(->type) else f()
define 'is', (value)-> (type)-> if value()?.type == type().dataType then `_true()` else `_false()`
define 'eq', (a)-> (b)-> if a() == b() then `_true()` else` _false()`
define 'withType', (value)->(t)->(f)-> if type = getType(value()) then t()(->type) else f()

define '+', global, (a)->(b)->a() + b()
define '-', global, (a)->(b)->a() - b()
define '*', global, (a)->(b)->a() * b()
define '/', global, (a)->(b)->a() / b()
define '%', global, (a)->(b)->a() % b()
define '+', (a)->(b)->a() + b()
define '-', (a)->(b)->a() - b()
define '*', (a)->(b)->a() * b()
define '/', (a)->(b)->a() / b()
define '%', (a)->(b)->a() % b()

define '>', global, (a)->(b)->a() > b()
define '>=', global, (a)->(b)->a() >= b()
define '<', global, (a)->(b)->a() < b()
define '<=', global, (a)->(b)->a() <= b()
define '>', (a)->(b)->if a() > b() then `_true()` else `_false()`
define '>=', (a)->(b)->if a() >= b() then `_true()` else `_false()`
define '<', (a)->(b)->if a() < b() then `_true()` else `_false()`
define '<=', (a)->(b)->if a() <= b() then `_true()` else `_false()`

define 'randInt', global, (from)->(to)-> Math.floor(Math.random() * (to() - from() + 1)) + from();
define '++', (a)->a() + 1
define '--', (a)->a() - 1
define 'iszero', (a)-> if 0 == a() then `_true()` else` _false()`

define 'randInt', (from)->(to)-> Math.floor(Math.random() * (to() - from() + 1)) + from();

runMonad = (monad, cont)->
monad.cmd (value) ->
Expand All @@ -55,20 +59,20 @@
if binding != "end" then m.binding = binding
m

define 'end', global, "end"
define 'end', "end"

define 'bind', global, (m)->(binding)->
define 'bind', (m)->(binding)->
makeMonad binding(), (cont)-> runMonad m(), cont

define 'return', global, (v)->(binding)->
define 'return', (v)->(binding)->
makeMonad binding(), (cont) -> cont(v())

define 'print', global, (msg)->(binding)->
define 'print', (msg)->(binding)->
makeMonad binding(), (cont)->
write("#{msg()}\n")
cont(null)

define 'prompt', global, (msg)->(binding)->
define 'prompt', (msg)->(binding)->
makeMonad binding(), (cont)->
prompt(String(msg()), (input)-> cont(input))

Expand All @@ -79,9 +83,9 @@ makeMonad binding(), (cont) -> cont(v())
if l == _nil() then ""
else (head l) + concatList tail l

define 'concat', global, (l)-> concatList(l())
define 'concat', (l)-> concatList(l())

define 'js', global, (codeList)->(binding)->
define 'js', (codeList)->(binding)->
makeMonad binding(), (cont)->
cl = codeList()
if cl != _nil() && cl.type != 'cons' then throw new Error("js expects a list for its code")
Expand Down

0 comments on commit c90d5ea

Please sign in to comment.