mirror of
https://github.com/flynx/Slang.git
synced 2025-10-28 10:10:07 +00:00
style update...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
7c4d3d65d8
commit
f180cec3d9
0
.gitignore
vendored
Executable file → Normal file
0
.gitignore
vendored
Executable file → Normal file
235
slang.js
235
slang.js
@ -13,48 +13,51 @@ Array.prototype.toString = function(){
|
|||||||
|
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
|
|
||||||
function run(context){
|
var run =
|
||||||
|
function(context){
|
||||||
|
|
||||||
context.stack = context.stack == null ? [] : context.stack
|
context.stack = context.stack == null ?
|
||||||
|
[]
|
||||||
|
: context.stack
|
||||||
|
|
||||||
while(context.code.length > 0){
|
while(context.code.length > 0){
|
||||||
|
|
||||||
var cur = context.code.splice(0, 1)[0]
|
var cur = context.code.splice(0, 1)[0]
|
||||||
|
|
||||||
// exit...
|
// exit...
|
||||||
if(typeof(cur) == typeof('abc') && cur == '_exit'){
|
if(typeof(cur) == typeof('abc')
|
||||||
|
&& cur == '_exit'){
|
||||||
return context
|
return context
|
||||||
|
|
||||||
// word
|
// word
|
||||||
} else if(typeof(cur) == typeof('abc') && cur in context.ns){
|
} else if(typeof(cur) == typeof('abc')
|
||||||
|
&& cur in context.ns){
|
||||||
var word = context.ns[cur]
|
var word = context.ns[cur]
|
||||||
// low-level word...
|
// low-level word...
|
||||||
if(typeof(word) == typeof(function(){})){
|
if(typeof(word) == typeof(function(){})){
|
||||||
var res = context.ns[cur](context)
|
var res = context.ns[cur](context)
|
||||||
|
|
||||||
// hi-level word...
|
// hi-level word...
|
||||||
} else if(typeof(word) == typeof([]) && word && word.constructor.name == 'Array'){
|
} else if(typeof(word) == typeof([])
|
||||||
|
&& word
|
||||||
|
&& word.constructor.name == 'Array'){
|
||||||
// XXX add isolation with a continuation...
|
// XXX add isolation with a continuation...
|
||||||
context.code.splice.apply(context.code, [0, 0].concat(word))
|
context.code
|
||||||
|
.splice.apply(context.code, [0, 0].concat(word))
|
||||||
var res = undefined
|
var res = undefined
|
||||||
|
|
||||||
// variable...
|
// variable...
|
||||||
} else {
|
} else {
|
||||||
var res = word
|
var res = word }
|
||||||
}
|
|
||||||
|
|
||||||
if(res !== undefined){
|
res !== undefined
|
||||||
context.stack.push(res)
|
&& context.stack.push(res)
|
||||||
}
|
|
||||||
|
|
||||||
// everything else...
|
// everything else...
|
||||||
} else {
|
} else {
|
||||||
context.stack.push(cur)
|
context.stack.push(cur) } }
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return context
|
return context }
|
||||||
}
|
|
||||||
|
|
||||||
// XXX make this add '\n' / EOL words to the stream...
|
// XXX make this add '\n' / EOL words to the stream...
|
||||||
//var SPLITTER = /\s*\([^\)]*\)\s*|\s*--.*[\n$]|\s*"([^"]*)"\s*|\s*'([^']*)'\s*|\s+/m
|
//var SPLITTER = /\s*\([^\)]*\)\s*|\s*--.*[\n$]|\s*"([^"]*)"\s*|\s*'([^']*)'\s*|\s+/m
|
||||||
@ -90,24 +93,24 @@ var SPLITTER = RegExp([
|
|||||||
|
|
||||||
// helpers...
|
// helpers...
|
||||||
// XXX should these skip quoted ends?
|
// XXX should these skip quoted ends?
|
||||||
var collect = function(start, end){
|
var collect =
|
||||||
|
function(start, end){
|
||||||
return function(context){
|
return function(context){
|
||||||
var res = start ? [start] : []
|
var res = start ? [start] : []
|
||||||
var code = context.code
|
var code = context.code
|
||||||
var cur = code.shift()
|
var cur = code.shift()
|
||||||
res.push(cur)
|
res.push(cur)
|
||||||
while(cur != end && code.length > 0){
|
while(cur != end
|
||||||
|
&& code.length > 0){
|
||||||
cur = code.shift()
|
cur = code.shift()
|
||||||
res.push(cur)
|
res.push(cur) }
|
||||||
}
|
return res } }
|
||||||
return res
|
var drop =
|
||||||
}
|
function(start, end){
|
||||||
}
|
|
||||||
var drop = function(start, end){
|
|
||||||
var collector = collect(start, end)
|
var collector = collect(start, end)
|
||||||
//return function(context){ collector(context) }
|
//return function(context){ collector(context) }
|
||||||
return function(context){ console.log('XXX', collector(context).join(' ')) }
|
return function(context){
|
||||||
}
|
console.log('XXX', collector(context).join(' ')) } }
|
||||||
|
|
||||||
|
|
||||||
// pre-processor namespace...
|
// pre-processor namespace...
|
||||||
@ -132,13 +135,13 @@ var PRE_NAMESPACE = {
|
|||||||
var block = []
|
var block = []
|
||||||
var code = context.code
|
var code = context.code
|
||||||
var cur = code.splice(0, 1)[0]
|
var cur = code.splice(0, 1)[0]
|
||||||
while(cur != ']' && cur != ']]' && code.length > 0){
|
while(cur != ']'
|
||||||
|
&& cur != ']]'
|
||||||
|
&& code.length > 0){
|
||||||
if(cur == '['){
|
if(cur == '['){
|
||||||
cur = this['['](context)
|
cur = this['['](context) }
|
||||||
}
|
|
||||||
block.push(cur)
|
block.push(cur)
|
||||||
cur = code.splice(0, 1)[0]
|
cur = code.splice(0, 1)[0] }
|
||||||
}
|
|
||||||
// we need this to be able to jump out of all the nested blocks,
|
// we need this to be able to jump out of all the nested blocks,
|
||||||
// thus we'll keep the ']]' in code and remove it explicitly
|
// thus we'll keep the ']]' in code and remove it explicitly
|
||||||
// later...
|
// later...
|
||||||
@ -148,16 +151,16 @@ var PRE_NAMESPACE = {
|
|||||||
// ...at this point this seems a bit complex...
|
// ...at this point this seems a bit complex...
|
||||||
// ...if there are more than one ']]' in a structure
|
// ...if there are more than one ']]' in a structure
|
||||||
// this might stop being deterministic...
|
// this might stop being deterministic...
|
||||||
code.splice(0, 0, cur)
|
code.splice(0, 0, cur) }
|
||||||
}
|
if(code.length == 0
|
||||||
if(code.length == 0 && cur != ']' && cur != ']]'){
|
&& cur != ']'
|
||||||
console.error('Did not find expected "]".')
|
&& cur != ']]'){
|
||||||
}
|
console.error('Did not find expected "]".') }
|
||||||
return block
|
return block },
|
||||||
},
|
|
||||||
// drop the closing words...
|
// drop the closing words...
|
||||||
']]': function(context){},
|
']]': function(context){},
|
||||||
']': function(context){ console.error('Unexpected "]".') },
|
']': function(context){
|
||||||
|
console.error('Unexpected "]".') },
|
||||||
|
|
||||||
// XXX macros are not recursive...
|
// XXX macros are not recursive...
|
||||||
'macro:': function(context){
|
'macro:': function(context){
|
||||||
@ -166,11 +169,9 @@ var PRE_NAMESPACE = {
|
|||||||
|
|
||||||
// as we do not have blocks yet we need to manually collect one ;)
|
// as we do not have blocks yet we need to manually collect one ;)
|
||||||
if(cur[0] == '['){
|
if(cur[0] == '['){
|
||||||
cur = [ this['['](context) ]
|
cur = [ this['['](context) ] }
|
||||||
}
|
|
||||||
|
|
||||||
this[ident] = cur[0]
|
this[ident] = cur[0] },
|
||||||
},
|
|
||||||
|
|
||||||
// a no op...
|
// a no op...
|
||||||
'\n': function(){ },
|
'\n': function(){ },
|
||||||
@ -195,8 +196,7 @@ var NAMESPACE = {
|
|||||||
'_flip': function(context){
|
'_flip': function(context){
|
||||||
var stack = context.stack
|
var stack = context.stack
|
||||||
context.stack = context.code.reverse()
|
context.stack = context.code.reverse()
|
||||||
context.code = stack.reverse()
|
context.code = stack.reverse() },
|
||||||
},
|
|
||||||
|
|
||||||
// swap heads of stack and code
|
// swap heads of stack and code
|
||||||
// ... ns nc -- ...
|
// ... ns nc -- ...
|
||||||
@ -211,15 +211,20 @@ var NAMESPACE = {
|
|||||||
var l = context.stack.length
|
var l = context.stack.length
|
||||||
|
|
||||||
// we need to pad e_c and c_c to requested length...
|
// we need to pad e_c and c_c to requested length...
|
||||||
s_c = s_c.length < s ? s_c.concat(Array( s - s_c.length )) : s_c
|
s_c = s_c.length < s ?
|
||||||
c_c = c_c.length < c ? c_c.concat(Array( c - c_c.length )) : c_c
|
s_c.concat(Array( s - s_c.length ))
|
||||||
|
: s_c
|
||||||
|
c_c = c_c.length < c ?
|
||||||
|
c_c.concat(Array( c - c_c.length ))
|
||||||
|
: c_c
|
||||||
|
|
||||||
// XXX we also need to shove something more sensible in the
|
// XXX we also need to shove something more sensible in the
|
||||||
// padding that undefined...
|
// padding that undefined...
|
||||||
|
|
||||||
context.code.splice.apply(context.code, [0, 0].concat(s_c))
|
context.code
|
||||||
context.stack.splice.apply(context.stack, [l, 0].concat(c_c))
|
.splice.apply(context.code, [0, 0].concat(s_c))
|
||||||
},
|
context.stack
|
||||||
|
.splice.apply(context.stack, [l, 0].concat(c_c)) },
|
||||||
|
|
||||||
// encapsulate stack to a block...
|
// encapsulate stack to a block...
|
||||||
// ... -- [ ... ]
|
// ... -- [ ... ]
|
||||||
@ -232,8 +237,8 @@ var NAMESPACE = {
|
|||||||
'b2s': function(context){
|
'b2s': function(context){
|
||||||
var c = context.stack.pop()
|
var c = context.stack.pop()
|
||||||
c = c === undefined ? [] : c
|
c = c === undefined ? [] : c
|
||||||
context.stack.splice.apply(context.stack, [context.stack.length, 0].concat(c))
|
context.stack
|
||||||
},
|
.splice.apply(context.stack, [context.stack.length, 0].concat(c)) },
|
||||||
'print': function(context){
|
'print': function(context){
|
||||||
console.log('>>>', context.stack[context.stack.length-1]) },
|
console.log('>>>', context.stack[context.stack.length-1]) },
|
||||||
|
|
||||||
@ -246,8 +251,7 @@ var NAMESPACE = {
|
|||||||
// XXX BUG: '"aaa" "bbb"' translates to ['"aaa"', '" "', '"bbb"']
|
// XXX BUG: '"aaa" "bbb"' translates to ['"aaa"', '" "', '"bbb"']
|
||||||
// i.e. quotes w/o whitespace are eaten...
|
// i.e. quotes w/o whitespace are eaten...
|
||||||
if(/^\s*(['"]).*\1\s*$/m.test(code)){
|
if(/^\s*(['"]).*\1\s*$/m.test(code)){
|
||||||
code = code.split(/^\s*(['"])(.*)\1\s*$/m)[2]
|
code = code.split(/^\s*(['"])(.*)\1\s*$/m)[2] }
|
||||||
}
|
|
||||||
|
|
||||||
//console.log(code)
|
//console.log(code)
|
||||||
|
|
||||||
@ -260,18 +264,14 @@ var NAMESPACE = {
|
|||||||
if(/^[-+]?[0-9]+\.[0-9]+$/.test(e)){
|
if(/^[-+]?[0-9]+\.[0-9]+$/.test(e)){
|
||||||
e = parseFloat(e)
|
e = parseFloat(e)
|
||||||
} else if(/^[-+]?[0-9]+$/.test(e)){
|
} else if(/^[-+]?[0-9]+$/.test(e)){
|
||||||
e = parseInt(e)
|
e = parseInt(e) }
|
||||||
}
|
return e })
|
||||||
return e
|
|
||||||
})
|
|
||||||
// remove undefined groups...
|
// remove undefined groups...
|
||||||
.filter(function(e){
|
.filter(function(e){
|
||||||
// NOTE: in JS 0 == '' is true ;)
|
// NOTE: in JS 0 == '' is true ;)
|
||||||
return e !== undefined && e !== ''
|
return e !== undefined
|
||||||
})
|
&& e !== '' }) }
|
||||||
}
|
return code },
|
||||||
return code
|
|
||||||
},
|
|
||||||
// pre-process a lexical list...
|
// pre-process a lexical list...
|
||||||
// a -- b
|
// a -- b
|
||||||
'prep': function(context){
|
'prep': function(context){
|
||||||
@ -282,18 +282,18 @@ var NAMESPACE = {
|
|||||||
code: code,
|
code: code,
|
||||||
ns: context.pre_ns,
|
ns: context.pre_ns,
|
||||||
pre_ns: {},
|
pre_ns: {},
|
||||||
}).stack
|
}).stack },
|
||||||
},
|
|
||||||
|
|
||||||
// s c -- s
|
// s c -- s
|
||||||
'_exec': function(context){
|
'_exec': function(context){
|
||||||
// block...
|
// block...
|
||||||
var b = context.stack.pop()
|
var b = context.stack.pop()
|
||||||
if(typeof(b) == typeof([]) && b && b.constructor.name == 'Array'){
|
if(typeof(b) == typeof([])
|
||||||
|
&& b
|
||||||
|
&& b.constructor.name == 'Array'){
|
||||||
b = b.slice()
|
b = b.slice()
|
||||||
} else {
|
} else {
|
||||||
b = [ b ]
|
b = [ b ] }
|
||||||
}
|
|
||||||
// stack...
|
// stack...
|
||||||
var s = context.stack.pop()
|
var s = context.stack.pop()
|
||||||
var res = run({
|
var res = run({
|
||||||
@ -306,34 +306,28 @@ var NAMESPACE = {
|
|||||||
// XXX is this the right way to go?
|
// XXX is this the right way to go?
|
||||||
context.ns = res.ns
|
context.ns = res.ns
|
||||||
context.pre_ns = res.pre_ns
|
context.pre_ns = res.pre_ns
|
||||||
return res.stack
|
return res.stack },
|
||||||
},
|
|
||||||
// quote - push the next elem as-is to stack...
|
// quote - push the next elem as-is to stack...
|
||||||
// -- x
|
// -- x
|
||||||
'\\': function(context){
|
'\\': function(context){
|
||||||
return context.code.splice(0, 1)[0] },
|
return context.code
|
||||||
|
.splice(0, 1)[0] },
|
||||||
|
|
||||||
// comparisons and logic...
|
// comparisons and logic...
|
||||||
// a b -- c
|
// a b -- c
|
||||||
'and': function(context){
|
'and': function(context){
|
||||||
var b = context.stack.pop()
|
var b = context.stack.pop()
|
||||||
var a = context.stack.pop()
|
var a = context.stack.pop()
|
||||||
if(a){
|
return a ?
|
||||||
return b
|
b
|
||||||
} else {
|
: a },
|
||||||
return a
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// a b -- c
|
// a b -- c
|
||||||
'or': function(context){
|
'or': function(context){
|
||||||
var b = context.stack.pop()
|
var b = context.stack.pop()
|
||||||
var a = context.stack.pop()
|
var a = context.stack.pop()
|
||||||
if(a){
|
return a ?
|
||||||
return a
|
a
|
||||||
} else {
|
: b },
|
||||||
return b
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// x -- b
|
// x -- b
|
||||||
'not': function(context){
|
'not': function(context){
|
||||||
return !context.stack.pop() },
|
return !context.stack.pop() },
|
||||||
@ -388,17 +382,16 @@ var NAMESPACE = {
|
|||||||
// block/list operations...
|
// block/list operations...
|
||||||
'block?': function(context){
|
'block?': function(context){
|
||||||
var e = context.stack.pop()
|
var e = context.stack.pop()
|
||||||
return typeof(e) == typeof([]) && e && e.constructor.name == 'Array'
|
return typeof(e) == typeof([])
|
||||||
},
|
&& e
|
||||||
|
&& e.constructor.name == 'Array' },
|
||||||
// b n -- b e
|
// b n -- b e
|
||||||
'at': function(context){
|
'at': function(context){
|
||||||
var i = context.stack.pop()
|
var i = context.stack.pop()
|
||||||
if(i < 0){
|
if(i < 0){
|
||||||
var l = context.stack[context.stack.length-1]
|
var l = context.stack[context.stack.length-1]
|
||||||
return l[l.length + i]
|
return l[l.length + i] }
|
||||||
}
|
return context.stack[context.stack.length-1][i] },
|
||||||
return context.stack[context.stack.length-1][i]
|
|
||||||
},
|
|
||||||
// b e n -- b
|
// b e n -- b
|
||||||
'to': function(context){
|
'to': function(context){
|
||||||
var i = context.stack.pop()
|
var i = context.stack.pop()
|
||||||
@ -407,9 +400,7 @@ var NAMESPACE = {
|
|||||||
var l = context.stack[context.stack.length-1]
|
var l = context.stack[context.stack.length-1]
|
||||||
l[l.length + i] = e
|
l[l.length + i] = e
|
||||||
} else {
|
} else {
|
||||||
context.stack[context.stack.length-1][i] = e
|
context.stack[context.stack.length-1][i] = e } },
|
||||||
}
|
|
||||||
},
|
|
||||||
// b e n -- b
|
// b e n -- b
|
||||||
'before': function(context){
|
'before': function(context){
|
||||||
var i = context.stack.pop()
|
var i = context.stack.pop()
|
||||||
@ -418,9 +409,7 @@ var NAMESPACE = {
|
|||||||
var l = context.stack[context.stack.length-1]
|
var l = context.stack[context.stack.length-1]
|
||||||
l.splice(l.length + i, 0, e)
|
l.splice(l.length + i, 0, e)
|
||||||
} else {
|
} else {
|
||||||
context.stack[context.stack.length-1].splice(i, 0, e)
|
context.stack[context.stack.length-1].splice(i, 0, e) } },
|
||||||
}
|
|
||||||
},
|
|
||||||
// b -- b e
|
// b -- b e
|
||||||
'pop': function(context){
|
'pop': function(context){
|
||||||
return context.stack[context.stack.length-1].pop() },
|
return context.stack[context.stack.length-1].pop() },
|
||||||
@ -446,10 +435,7 @@ var NAMESPACE = {
|
|||||||
i--
|
i--
|
||||||
} else {
|
} else {
|
||||||
b.splice.apply(b, [i, 1].concat(res))
|
b.splice.apply(b, [i, 1].concat(res))
|
||||||
i += l - 1
|
i += l - 1 } } },
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
// object stuff...
|
// object stuff...
|
||||||
@ -457,8 +443,8 @@ var NAMESPACE = {
|
|||||||
|
|
||||||
'object?': function(context){
|
'object?': function(context){
|
||||||
var o = context.stack[context.stack.length - 1]
|
var o = context.stack[context.stack.length - 1]
|
||||||
return o && o.constructor === Object
|
return o
|
||||||
},
|
&& o.constructor === Object },
|
||||||
|
|
||||||
// set item...
|
// set item...
|
||||||
// o k v -- o
|
// o k v -- o
|
||||||
@ -490,8 +476,7 @@ var NAMESPACE = {
|
|||||||
var v = o[k]
|
var v = o[k]
|
||||||
delete o[k]
|
delete o[k]
|
||||||
|
|
||||||
return v
|
return v },
|
||||||
},
|
|
||||||
|
|
||||||
// o -- k
|
// o -- k
|
||||||
'keys': function(context){
|
'keys': function(context){
|
||||||
@ -503,9 +488,10 @@ var NAMESPACE = {
|
|||||||
'proto!': function(context){
|
'proto!': function(context){
|
||||||
var b = context.stack.pop()
|
var b = context.stack.pop()
|
||||||
var a = context.stack.pop()
|
var a = context.stack.pop()
|
||||||
b.__proto__ = a === false ? {}.__proto__ : a
|
b.__proto__ = a === false ?
|
||||||
return b
|
{}.__proto__
|
||||||
},
|
: a
|
||||||
|
return b },
|
||||||
|
|
||||||
// o -- p
|
// o -- p
|
||||||
// XXX what should this be:
|
// XXX what should this be:
|
||||||
@ -1064,25 +1050,24 @@ run(CONTEXT)
|
|||||||
|
|
||||||
// convenience...
|
// convenience...
|
||||||
function _slang(code, context){
|
function _slang(code, context){
|
||||||
context = context == null ? CONTEXT : context
|
context = context == null ?
|
||||||
|
CONTEXT
|
||||||
|
: context
|
||||||
context.code = code
|
context.code = code
|
||||||
return run(context).stack
|
return run(context).stack }
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function slang(code, context){
|
function slang(code, context){
|
||||||
context = context == null ? CONTEXT : context
|
context = context == null ?
|
||||||
|
CONTEXT
|
||||||
|
: context
|
||||||
|
|
||||||
if(typeof(code) == typeof('abc')){
|
code = typeof(code) == typeof('abc') ?
|
||||||
code = [ '\\', code, 'lex', 'prep', 'exec' ]
|
[ '\\', code, 'lex', 'prep', 'exec' ]
|
||||||
} else {
|
: [ code, 'prep', 'exec' ]
|
||||||
code = [ code, 'prep', 'exec' ]
|
|
||||||
}
|
|
||||||
|
|
||||||
context.code = code
|
context.code = code
|
||||||
return run(context).stack
|
return run(context).stack }
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1098,11 +1083,10 @@ var RS_PRE_NAMESPACE = {
|
|||||||
var cur = code.splice(0, 1)[0]
|
var cur = code.splice(0, 1)[0]
|
||||||
while(cur != ';' && code.length > 0){
|
while(cur != ';' && code.length > 0){
|
||||||
line.push(cur)
|
line.push(cur)
|
||||||
cur = code.splice(0, 1)[0]
|
cur = code.splice(0, 1)[0] }
|
||||||
}
|
|
||||||
|
|
||||||
context.code.splice.apply(context.code, [0, 0].concat(line.reverse()))
|
context.code
|
||||||
},
|
.splice.apply(context.code, [0, 0].concat(line.reverse())) },
|
||||||
|
|
||||||
'[': PRE_NAMESPACE['['],
|
'[': PRE_NAMESPACE['['],
|
||||||
'macro:': PRE_NAMESPACE['macro:'],
|
'macro:': PRE_NAMESPACE['macro:'],
|
||||||
@ -1121,10 +1105,11 @@ run(RS_CONTEXT)
|
|||||||
RS_CONTEXT.pre_ns = RS_PRE_NAMESPACE
|
RS_CONTEXT.pre_ns = RS_PRE_NAMESPACE
|
||||||
|
|
||||||
function rslang(code, context){
|
function rslang(code, context){
|
||||||
context = context == null ? RS_CONTEXT : context
|
context = context == null ?
|
||||||
|
RS_CONTEXT
|
||||||
|
: context
|
||||||
|
|
||||||
return slang(code, context)
|
return slang(code, context) }
|
||||||
}
|
|
||||||
//*/
|
//*/
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user