style update...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2022-02-22 22:53:29 +03:00
parent 7c4d3d65d8
commit f180cec3d9
3 changed files with 110 additions and 125 deletions

0
.gitignore vendored Executable file → Normal file
View File

0
README.md Executable file → Normal file
View File

235
slang.js
View File

@ -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) }
}
//*/ //*/