mirror of
				https://github.com/flynx/Course-JavaScript.git
				synced 2025-11-04 05:50:08 +00:00 
			
		
		
		
	add a small stack language called Slang...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
		
							parent
							
								
									13b436456d
								
							
						
					
					
						commit
						b99fc69bd2
					
				
							
								
								
									
										11
									
								
								Slang/slang.html
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										11
									
								
								Slang/slang.html
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,11 @@
 | 
			
		||||
<html>
 | 
			
		||||
<script src="slang.js"></script>
 | 
			
		||||
<body>
 | 
			
		||||
</body>
 | 
			
		||||
<script>
 | 
			
		||||
document.body.innerHTML='<pre>'+BOOTSTRAP
 | 
			
		||||
		.replace(/&/g, '&')
 | 
			
		||||
		.replace(/>/g, '>')
 | 
			
		||||
		.replace(/</g, '<')+'</pre>'
 | 
			
		||||
</script>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										504
									
								
								Slang/slang.js
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										504
									
								
								Slang/slang.js
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,504 @@
 | 
			
		||||
/**********************************************************************
 | 
			
		||||
* 
 | 
			
		||||
*
 | 
			
		||||
*
 | 
			
		||||
**********************************************************************/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*********************************************************************/
 | 
			
		||||
 | 
			
		||||
function run(context){
 | 
			
		||||
 | 
			
		||||
	var stack = context.stack
 | 
			
		||||
	stack = stack == null ? [] : stack
 | 
			
		||||
	context.stack = stack
 | 
			
		||||
 | 
			
		||||
	var ns = context.ns
 | 
			
		||||
 | 
			
		||||
	while(context.code.length > 0){
 | 
			
		||||
 | 
			
		||||
		var cur = context.code.splice(0, 1)[0]
 | 
			
		||||
 | 
			
		||||
		// exit...
 | 
			
		||||
		if(typeof(cur) == typeof('abc') && cur == '_exit'){
 | 
			
		||||
			return context
 | 
			
		||||
 | 
			
		||||
		// word
 | 
			
		||||
		} else if(typeof(cur) == typeof('abc') && cur in ns){
 | 
			
		||||
			var word = ns[cur]
 | 
			
		||||
			// low-level word...
 | 
			
		||||
			if(typeof(word) == typeof(function(){})){
 | 
			
		||||
				var res = ns[cur](context)
 | 
			
		||||
 | 
			
		||||
			// hi-level word...
 | 
			
		||||
			} else if(typeof(word) == typeof([]) && word.constructor.name == 'Array'){
 | 
			
		||||
				// XXX add isolation with a continuation...
 | 
			
		||||
				context.code.splice.apply(context.code, [0, 0].concat(word))
 | 
			
		||||
				var res = null
 | 
			
		||||
 | 
			
		||||
			// variable...
 | 
			
		||||
			} else {
 | 
			
		||||
				res = word
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if(res != null){
 | 
			
		||||
				context.stack.push(res)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		// everything else...
 | 
			
		||||
		} else {
 | 
			
		||||
			context.stack.push(cur)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return context
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var SPLITTER = /\s*\([^\)]*\)\s*|\s*--.*[\n$]|\s*(".*")\s*|\s*('.*')\s*|\s+/m
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// pre-processor namespace...
 | 
			
		||||
var PRE_NAMESPACE = {
 | 
			
		||||
	// XXX use the real reader...
 | 
			
		||||
	// block...
 | 
			
		||||
	// syntax: [ ... ]
 | 
			
		||||
	'[': function(context){
 | 
			
		||||
		var block = []
 | 
			
		||||
		var code = context.code
 | 
			
		||||
		var cur = code.splice(0, 1)[0]
 | 
			
		||||
		while(cur != ']' && code.length > 0){
 | 
			
		||||
			if(cur == '['){
 | 
			
		||||
				cur = this['['](context)
 | 
			
		||||
			}
 | 
			
		||||
			block.push(cur)
 | 
			
		||||
			cur = code.splice(0, 1)[0]
 | 
			
		||||
		}
 | 
			
		||||
		if(code.length == 0 && cur != ']'){
 | 
			
		||||
			console.error('Did not find expected "]".')
 | 
			
		||||
		} 
 | 
			
		||||
		return block
 | 
			
		||||
	},
 | 
			
		||||
	'macro:': function(context){
 | 
			
		||||
		var ident = context.code.splice(0, 1)
 | 
			
		||||
		var cur = context.code.splice(0, 1)
 | 
			
		||||
 | 
			
		||||
		// as we do not have blocks yet we need to manually collect one ;)
 | 
			
		||||
		if(cur[0] == '['){
 | 
			
		||||
			cur = [ this['['](context) ]
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		this[ident] = cur[0]
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// main namespace...
 | 
			
		||||
var NAMESPACE = {
 | 
			
		||||
	// constants...
 | 
			
		||||
	'true': true,
 | 
			
		||||
	'false': false,
 | 
			
		||||
	// this is mutable, so we'll need to create a new instance each time
 | 
			
		||||
	'[]': function(){ return [] }, 
 | 
			
		||||
 | 
			
		||||
	'nop': function(){}, 
 | 
			
		||||
 | 
			
		||||
	// XXX experimental...
 | 
			
		||||
	// flip the code and stack...
 | 
			
		||||
	// ... -- ...
 | 
			
		||||
	'_flip': function(context){
 | 
			
		||||
		var stack = context.stack
 | 
			
		||||
		context.stack = context.code.reverse()
 | 
			
		||||
		context.code = stack.reverse()
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	// swap heads of stack and code
 | 
			
		||||
	// ... ns nc -- ...
 | 
			
		||||
	'_swapN': function(context){ 
 | 
			
		||||
		var c = context.stack.pop()
 | 
			
		||||
		var s = context.stack.pop()
 | 
			
		||||
		var l = context.stack.length
 | 
			
		||||
 | 
			
		||||
		// get the stack/code sections to swap...
 | 
			
		||||
		var s_c = context.stack.splice(l-s, l)
 | 
			
		||||
		var c_c = context.code.splice(0, c)
 | 
			
		||||
		var l = context.stack.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
 | 
			
		||||
		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 
 | 
			
		||||
		// 		padding that undefined...
 | 
			
		||||
 | 
			
		||||
		context.code.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...
 | 
			
		||||
	// ... -- [ ... ]
 | 
			
		||||
	's2b': function(context){
 | 
			
		||||
		context.stack = [ context.stack ]
 | 
			
		||||
	},
 | 
			
		||||
	// expand block to stack... 
 | 
			
		||||
	// NOTE: this will append the block contents to stack, w.o. replacing 
 | 
			
		||||
	// 		stack contents. this is different to _s2b
 | 
			
		||||
	// ... [ ... ] -- ... ...
 | 
			
		||||
	'b2s': function(context){
 | 
			
		||||
		var c = context.stack.pop()
 | 
			
		||||
		context.stack.splice.apply(context.stack, [context.stack.length, 0].concat(c))
 | 
			
		||||
	},
 | 
			
		||||
	'print': function(context){
 | 
			
		||||
		console.log('>>>', context.stack[context.stack.length-1])
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	// turn a sting into a lexical list...
 | 
			
		||||
	// c -- b
 | 
			
		||||
	// XXX BUG see code...
 | 
			
		||||
	'lex': function(context){
 | 
			
		||||
		code = context.stack.pop()
 | 
			
		||||
		if(typeof(code) == typeof('abc')){
 | 
			
		||||
			// XXX BUG: '"aaa" "bbb"' translates to ['"aaa"', '" "', '"bbb"'] 
 | 
			
		||||
			// 		i.e. quotes w/o whitespace are eaten...
 | 
			
		||||
			if(/^(['"]).*\1$/m.test(code)){
 | 
			
		||||
				code = code.split(/^(['"])(.*)\1$/m)[2]
 | 
			
		||||
			}
 | 
			
		||||
			var res = []
 | 
			
		||||
			code = code
 | 
			
		||||
				// split by strings whitespace and block comments...
 | 
			
		||||
				.split(SPLITTER)
 | 
			
		||||
				// parse numbers...
 | 
			
		||||
				.map(function(e){ 
 | 
			
		||||
					// numbers...
 | 
			
		||||
					if(/^[-+]?[0-9]+\.[0-9]+$/.test(e)){
 | 
			
		||||
						e = parseFloat(e)
 | 
			
		||||
					} else if(/^[-+]?[0-9]+$/.test(e)){
 | 
			
		||||
						e = parseInt(e)
 | 
			
		||||
					}
 | 
			
		||||
					return e
 | 
			
		||||
				})
 | 
			
		||||
				// remove undefined groups...
 | 
			
		||||
				.filter(function(e){ 
 | 
			
		||||
					// NOTE: in JS 0 == '' is true ;)
 | 
			
		||||
					return e !== undefined && e !== ''
 | 
			
		||||
				})
 | 
			
		||||
		}
 | 
			
		||||
		return code
 | 
			
		||||
	},
 | 
			
		||||
	// pre-process a lexical list...
 | 
			
		||||
	// a -- b
 | 
			
		||||
	'prep': function(context){
 | 
			
		||||
		var code = context.stack.pop()
 | 
			
		||||
 | 
			
		||||
		return run({
 | 
			
		||||
			stack: [],
 | 
			
		||||
			code: code,
 | 
			
		||||
			ns: context.pre_ns,
 | 
			
		||||
			pre_ns: {},
 | 
			
		||||
		}).stack
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	// word definition...
 | 
			
		||||
	// syntax: :: <ident> <block>
 | 
			
		||||
	// --
 | 
			
		||||
	'::': function(context){
 | 
			
		||||
		var ident = context.code.splice(0, 1)
 | 
			
		||||
		var cur = context.code.splice(0, 1)
 | 
			
		||||
 | 
			
		||||
		this[ident] = cur[0]
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	// s c -- s
 | 
			
		||||
	'_exec': function(context){
 | 
			
		||||
		// block...
 | 
			
		||||
		var b = context.stack.pop()
 | 
			
		||||
		if(typeof(b) == typeof([]) && b.constructor.name == 'Array'){
 | 
			
		||||
			b = b.slice()
 | 
			
		||||
		} else {
 | 
			
		||||
			b = [ b ]
 | 
			
		||||
		}
 | 
			
		||||
		// stack...
 | 
			
		||||
		var s = context.stack.pop()
 | 
			
		||||
		var res = run({
 | 
			
		||||
			stack: s,
 | 
			
		||||
			code: b,
 | 
			
		||||
			// NOTE: this can have side-effects on the context...
 | 
			
		||||
			ns: context.ns,
 | 
			
		||||
			pre_ns: context.pre_ns
 | 
			
		||||
		}).stack
 | 
			
		||||
		return res
 | 
			
		||||
	},
 | 
			
		||||
	// quote - push the next elem as-is to stack...
 | 
			
		||||
	// -- x
 | 
			
		||||
	'\\': function(context){
 | 
			
		||||
		var code = context.code
 | 
			
		||||
		return code.splice(0, 1)[0] 
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	// comparisons and logic...
 | 
			
		||||
	// a b -- c
 | 
			
		||||
	'and': function(context){
 | 
			
		||||
		var b = context.stack.pop()
 | 
			
		||||
		var a = context.stack.pop()
 | 
			
		||||
		if(a){
 | 
			
		||||
			return b
 | 
			
		||||
		} else {
 | 
			
		||||
			return a
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	// a b -- c
 | 
			
		||||
	'or': function(context){
 | 
			
		||||
		var b = context.stack.pop()
 | 
			
		||||
		var a = context.stack.pop()
 | 
			
		||||
		if(a){
 | 
			
		||||
			return a
 | 
			
		||||
		} else {
 | 
			
		||||
			return b
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	// x -- b
 | 
			
		||||
	'not': function(context){
 | 
			
		||||
		return !context.stack.pop()
 | 
			
		||||
	},
 | 
			
		||||
	// a b -- c
 | 
			
		||||
	'gt': function(context){
 | 
			
		||||
		return context.stack.pop() < context.stack.pop()
 | 
			
		||||
	},
 | 
			
		||||
	// a b -- c
 | 
			
		||||
	'eq': function(context){
 | 
			
		||||
		return context.stack.pop() == context.stack.pop()
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	// stack operations...
 | 
			
		||||
	// ... x -- x ...
 | 
			
		||||
	'rot': function(context){
 | 
			
		||||
		context.stack.splice(0, 0, context.stack.pop())
 | 
			
		||||
	},
 | 
			
		||||
	// x ... -- ... x
 | 
			
		||||
	'tor': function(context){
 | 
			
		||||
		context.stack.push(context.stack.shift())
 | 
			
		||||
	},
 | 
			
		||||
	// a b -- b a
 | 
			
		||||
	'swap': function(context){
 | 
			
		||||
		return context.stack.splice(context.stack.length-2, 1)[0]
 | 
			
		||||
	},
 | 
			
		||||
	// x -- x x
 | 
			
		||||
	'dup': function(context){
 | 
			
		||||
		return context.stack[context.stack.length-1]
 | 
			
		||||
	},
 | 
			
		||||
	// x --
 | 
			
		||||
	'drop': function(context){
 | 
			
		||||
		context.stack.pop()
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	// basic number operations...
 | 
			
		||||
	// a -- b
 | 
			
		||||
	'isNumber': function(context){
 | 
			
		||||
		return typeof(context.stack.pop()) == typeof(123)
 | 
			
		||||
	},
 | 
			
		||||
	// a b -- c
 | 
			
		||||
	'add': function(context){
 | 
			
		||||
		return context.stack.pop() + context.stack.pop()
 | 
			
		||||
	},
 | 
			
		||||
	'sub': function(context){
 | 
			
		||||
		return - context.stack.pop() + context.stack.pop()
 | 
			
		||||
	},
 | 
			
		||||
	'mul': function(context){
 | 
			
		||||
		return context.stack.pop() * context.stack.pop()
 | 
			
		||||
	},
 | 
			
		||||
	'div': function(context){
 | 
			
		||||
		return context.stack.pop() / context.stack.pop()
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	// block/list operations...
 | 
			
		||||
	'isBlock': function(context){
 | 
			
		||||
		var e = context.stack.pop()
 | 
			
		||||
		return typeof(e) == typeof([]) && e.constructor.name == 'Array'
 | 
			
		||||
	},
 | 
			
		||||
	// b n -- b e
 | 
			
		||||
	'at': function(context){
 | 
			
		||||
		var i = context.stack.pop()
 | 
			
		||||
		if(i < 0){
 | 
			
		||||
			var l = context.stack[context.stack.length-1]
 | 
			
		||||
			return l[l.length + i]
 | 
			
		||||
		}
 | 
			
		||||
		return context.stack[context.stack.length-1][i]
 | 
			
		||||
	},
 | 
			
		||||
	// b e n -- b
 | 
			
		||||
	'to': function(context){
 | 
			
		||||
		var i = context.stack.pop()
 | 
			
		||||
		var e = context.stack.pop()
 | 
			
		||||
		if(i < 0){
 | 
			
		||||
			var l = context.stack[context.stack.length-1]
 | 
			
		||||
			l[l.length + i] = e
 | 
			
		||||
		} else {
 | 
			
		||||
			context.stack[context.stack.length-1][i] = e
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	// b e n -- b
 | 
			
		||||
	'before': function(context){
 | 
			
		||||
		var i = context.stack.pop()
 | 
			
		||||
		var e = context.stack.pop()
 | 
			
		||||
		if(i < 0){
 | 
			
		||||
			var l = context.stack[context.stack.length-1]
 | 
			
		||||
			l.splice(l.length + i + 1, 0, e)
 | 
			
		||||
		} else {
 | 
			
		||||
			context.stack[context.stack.length-1].splice(i, 0, e)
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	// b -- b e
 | 
			
		||||
	'pop': function(context){
 | 
			
		||||
		return context.stack[context.stack.length-1].pop()
 | 
			
		||||
	},
 | 
			
		||||
	// b -- b l
 | 
			
		||||
	'len': function(context){
 | 
			
		||||
		return context.stack[context.stack.length-1].length
 | 
			
		||||
	},
 | 
			
		||||
	// b c -- b
 | 
			
		||||
	'each': function(context){
 | 
			
		||||
		var c = context.stack.pop()
 | 
			
		||||
		var b = context.stack[context.stack.length-1]
 | 
			
		||||
		for(var i=0; i < b.length; i++){
 | 
			
		||||
			// exec block in a separate context...
 | 
			
		||||
			var res = run({
 | 
			
		||||
				stack: [b[i], c],
 | 
			
		||||
				code: ['exec'],
 | 
			
		||||
				// NOTE: this can have side-effects on the context...
 | 
			
		||||
				ns: context.ns
 | 
			
		||||
			}).stack
 | 
			
		||||
			var l = res.length
 | 
			
		||||
			if(l == 0){
 | 
			
		||||
				b.splice(i, 1)
 | 
			
		||||
				i--
 | 
			
		||||
			} else {
 | 
			
		||||
				b.splice.apply(b, [i, 1].concat(res))
 | 
			
		||||
				i += l - 1
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
var BOOTSTRAP = '\n'+
 | 
			
		||||
':: _swap ( x -- y ) [ 1 1 _swapN ]\n'+
 | 
			
		||||
':: _push ( x -- y ) [ 0 _swapN ]\n'+
 | 
			
		||||
':: _pull ( x -- y ) [ 0 swap _swapN ]\n'+
 | 
			
		||||
'\n'+
 | 
			
		||||
':: exec ( b -- ... ) [ s2b pop _exec b2s ]\n'+
 | 
			
		||||
':: eval ( c -- ... ) [ lex prep exec ]\n'+
 | 
			
		||||
'-- like exec but will run a block in current context...\n'+
 | 
			
		||||
':: b2c [ len rot b2s tor 0 _swapN ]\n'+
 | 
			
		||||
'\n'+
 | 
			
		||||
':: . ( x -- ) [ print drop ]\n'+
 | 
			
		||||
'\n'+
 | 
			
		||||
':: swap2 ( a _ b -- b _ a ) [ swap rot swap tor swap ]\n'+
 | 
			
		||||
'\n'+
 | 
			
		||||
':: isT ( a -- b ) [ not not true eq ]\n'+
 | 
			
		||||
':: isF ( a -- b ) [ not isT ]\n'+
 | 
			
		||||
//'\n'+
 | 
			
		||||
//':: if ( cond a b -- ... ) [ rot rot exec isT tor and tor or exec ]\n'+
 | 
			
		||||
'\n'+
 | 
			
		||||
'-- [ <cond> ] ? [ <main> ] \n'+
 | 
			
		||||
'-- [ <cond> ] ? [ <main> ] else [ <else> ] \n'+
 | 
			
		||||
':: _run_else [ drop dup \\ else eq [ drop \\ exec _swap 4 ] and\n'+
 | 
			
		||||
'				[ 1 _push 2 ] or\n'+
 | 
			
		||||
'				b2s 0 _swapN ]\n'+
 | 
			
		||||
':: _run_then [ \\ exec swap dup \\ else eq [ (drop else) drop \\ drop _swap 6 ] and\n'+
 | 
			
		||||
'				[ (run as-is) 1 _push 4 ] or\n'+
 | 
			
		||||
'				b2s 0 _swapN ]\n'+
 | 
			
		||||
// XXX BUG: if no code after this will break...
 | 
			
		||||
// 		Ex:
 | 
			
		||||
// 			-- this will not exec [ B ]...
 | 
			
		||||
// 			[ A ] ? [ B ]
 | 
			
		||||
// 			-- while this will...
 | 
			
		||||
// 			[ A ] ? [ B ] nop
 | 
			
		||||
':: ? [ exec [ _run_then 1 ] and [ swap _run_else 2 ] or b2s 2 _swapN ]\n'+
 | 
			
		||||
'\n'+
 | 
			
		||||
'\n'+
 | 
			
		||||
'-- list/block 2\'nd gen stuff...\n'+
 | 
			
		||||
':: push ( b e i -- b ) [ -1 before ]\n'+
 | 
			
		||||
'\n'+
 | 
			
		||||
'\n'+
 | 
			
		||||
'-- experimental...\n'+
 | 
			
		||||
'-- NOTE: these are at this point stupid and do not support priorities or grouping...\n'+
 | 
			
		||||
'-- NOTE: these have both stack and code effect, in genera the operations are of \n'+
 | 
			
		||||
'--		the form: A op B\n'+
 | 
			
		||||
':: + [ \\ add _swap ]\n'+
 | 
			
		||||
':: - [ \\ sub _swap ]\n'+
 | 
			
		||||
':: * [ \\ mul _swap ]\n'+
 | 
			
		||||
':: / [ \\ div _swap ]\n'+
 | 
			
		||||
'\n'+
 | 
			
		||||
':: == [ \\ eq _swap ]\n'+
 | 
			
		||||
':: > [ \\ gt _swap ]\n'+
 | 
			
		||||
'\n'+
 | 
			
		||||
'\n'+
 | 
			
		||||
'-- this is here for devel use only\n'+
 | 
			
		||||
':: _clear ( * -- ) [ s2b drop ] \n'+
 | 
			
		||||
':: _stack_size ( -- l ) [ s2b len swap b2s tor ] \n'+
 | 
			
		||||
'\n'+
 | 
			
		||||
'\n'+
 | 
			
		||||
'-- tests and examples...\n'+
 | 
			
		||||
':: hi ( -- ) [ "Hello World!" print drop ]\n'+
 | 
			
		||||
//'-- NOTE: nop at the end is a stub to fix a bug in ? else ...\n'+
 | 
			
		||||
//':: ! ( a -- b ) [ [ dup 1 eq not ] ? [ dup 1 sub ! mul ] nop ]\n'+
 | 
			
		||||
':: ! ( a -- b ) [ [ dup 1 eq not ] ? [ dup 1 sub ! mul ] ]\n'+
 | 
			
		||||
':: range ( n -- b ) [\n'+
 | 
			
		||||
'		-- initial state...\n'+
 | 
			
		||||
'		[ dup isNumber ] ? \n'+
 | 
			
		||||
'			[ [] swap ]\n'+
 | 
			
		||||
'		-- get first elem...\n'+
 | 
			
		||||
'		else\n'+
 | 
			
		||||
'			[ 0 at ]\n'+
 | 
			
		||||
'		-- we got to the end...\n'+
 | 
			
		||||
'		[ dup 0 eq ] ? \n'+
 | 
			
		||||
'			[ drop ]\n'+
 | 
			
		||||
'		-- dec push new and continue...\n'+
 | 
			
		||||
'		else\n'+
 | 
			
		||||
'			[ 1 sub 0 before range ] ]\n'+
 | 
			
		||||
':: range2 ( n s -- b )\n'+
 | 
			
		||||
'		[ swap range swap [] swap push \\ * 0 before each ]\n'+
 | 
			
		||||
'\n'+
 | 
			
		||||
''
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
var STARTUP = [[], BOOTSTRAP, 'lex', 'prep', '_exec', 'drop']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// build bootstrap...
 | 
			
		||||
var CONTEXT = {
 | 
			
		||||
	stack: [],
 | 
			
		||||
	code: STARTUP.slice(),
 | 
			
		||||
	ns: NAMESPACE,
 | 
			
		||||
	pre_ns: PRE_NAMESPACE,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// run bootstrap...
 | 
			
		||||
run(CONTEXT)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// convenience...
 | 
			
		||||
function _slang(code, context){
 | 
			
		||||
	context = context == null ? CONTEXT : context
 | 
			
		||||
 | 
			
		||||
	context.code = code
 | 
			
		||||
	return run(context).stack
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function slang(code, context){
 | 
			
		||||
	context = context == null ? CONTEXT : context
 | 
			
		||||
 | 
			
		||||
	if(typeof(code) == typeof('abc')){
 | 
			
		||||
		code = [ '"'+code+'"', 'lex', 'prep', 'exec' ]
 | 
			
		||||
	} else {
 | 
			
		||||
		code = [ [code], 'b2s', 'prep', 'exec' ]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	context.code = code
 | 
			
		||||
	return run(context).stack
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**********************************************************************
 | 
			
		||||
* vim:set ts=4 sw=4 :                                                */
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user