mirror of
https://github.com/russolsen/sallyforth
synced 2024-12-26 21:58:32 +01:00
Clean up attr resolution.
This commit is contained in:
parent
965f78f142
commit
a4e2a1997a
5 changed files with 164 additions and 77 deletions
|
@ -1,17 +1,14 @@
|
||||||
"List" p
|
"List" p
|
||||||
|
|
||||||
: [n] (n list -- nth-item)
|
\ Index into the x'th item.
|
||||||
2 ->list \ Make the arg list.
|
: [x] (col key -- value) 1 ->list '__getitem__ .!! ;
|
||||||
<. builtins.list '__getitem__ .> \ Find the getitem method.
|
|
||||||
!! \ Call!
|
|
||||||
;
|
|
||||||
|
|
||||||
: first (list -- first-item) 0 swap [n] ;
|
: first (list -- first-item) 0 [x] ;
|
||||||
: second (list -- second-item) 1 swap [n] ;
|
: second (list -- second-item) 1 [x] ;
|
||||||
: third (list -- third-item) 2 swap [n] ;
|
: third (list -- third-item) 2 [x] ;
|
||||||
: fourth (list -- fourth-item) 3 swap [n] ;
|
: fourth (list -- fourth-item) 3 [x] ;
|
||||||
|
|
||||||
: last (list -- last-item) -1 swap [n] ;
|
: last (list -- last-item) -1 [x] ;
|
||||||
|
|
||||||
: slice (start stop -- slice-obj)
|
: slice (start stop -- slice-obj)
|
||||||
swap
|
swap
|
||||||
|
@ -22,15 +19,18 @@
|
||||||
|
|
||||||
: take (n list -- first-n-items)
|
: take (n list -- first-n-items)
|
||||||
swap 0 swap slice \ Make the 0..n slice.
|
swap 0 swap slice \ Make the 0..n slice.
|
||||||
swap [n] \ Do a[0..n].
|
[x] \ Do a[0..n].
|
||||||
;
|
;
|
||||||
|
|
||||||
: drop (n list -- all-but-first-n-items)
|
: drop (n list -- all-but-first-n-items)
|
||||||
swap nil slice \ Make the n..None slice.
|
swap nil slice \ Make the n..None slice.
|
||||||
swap [n]
|
[x]
|
||||||
;
|
;
|
||||||
|
|
||||||
|
: rest (list -- all-but-first) 1 swap drop ;
|
||||||
|
: rrest (list -- rest-of-rest) rest rest ;
|
||||||
|
: rrrest (list -- all-but-first) rest rest rest ;
|
||||||
|
|
||||||
|
: first (list -- first-item) 1 swap drop ;
|
||||||
|
: ffirst (list -- first-of-first) first first ;
|
||||||
|
: fffirst (list -- fff-irst) first first first ;
|
||||||
|
|
|
@ -62,7 +62,7 @@ class Namespace:
|
||||||
return self.contents.__iter__()
|
return self.contents.__iter__()
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
# print("get item", key, self.contents)
|
#print("get item", key, self.name)
|
||||||
if key in self.contents:
|
if key in self.contents:
|
||||||
return self.contents[key]
|
return self.contents[key]
|
||||||
# print("not in local ns")
|
# print("not in local ns")
|
||||||
|
|
|
@ -50,6 +50,7 @@ def repl(f):
|
||||||
line = input(p)
|
line = input(p)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("<<interrupt>>")
|
print("<<interrupt>>")
|
||||||
|
f.stack.reset()
|
||||||
line = ''
|
line = ''
|
||||||
except EOFError:
|
except EOFError:
|
||||||
break
|
break
|
||||||
|
|
|
@ -15,11 +15,11 @@
|
||||||
'dot '. alias
|
'dot '. alias
|
||||||
'colon ': alias
|
'colon ': alias
|
||||||
'semi '; alias
|
'semi '; alias
|
||||||
|
'thread '@@ alias
|
||||||
'bounded_list '[list] alias
|
'bounded_list '[list] alias
|
||||||
'list '->list alias
|
'list '->list alias
|
||||||
'to_arglist '->arglist alias
|
'to_arglist '->arglist alias
|
||||||
'list_to_map 'list->map alias
|
'list_to_map 'list->map alias
|
||||||
'lookup '@@ alias
|
|
||||||
'call '!! alias
|
'call '!! alias
|
||||||
'add '+ alias
|
'add '+ alias
|
||||||
'sub '- alias
|
'sub '- alias
|
||||||
|
@ -59,11 +59,8 @@
|
||||||
: [: [ ;
|
: [: [ ;
|
||||||
: :] ] ->arglist ;
|
: :] ] ->arglist ;
|
||||||
|
|
||||||
: => [ ;
|
|
||||||
: >! ] arrow ;
|
|
||||||
|
|
||||||
: <. [ ;
|
: <. [ ;
|
||||||
: .> ] arrow ;
|
: .> ] thread ;
|
||||||
|
|
||||||
: !!0 [] swap call ;
|
: !!0 [] swap call ;
|
||||||
|
|
||||||
|
@ -86,6 +83,7 @@
|
||||||
|
|
||||||
: -- -1 + ;
|
: -- -1 + ;
|
||||||
: ++ 1 + ;
|
: ++ 1 + ;
|
||||||
|
: *2 2 * ;
|
||||||
: pos? 0 > ;
|
: pos? 0 > ;
|
||||||
: neg? 0 < ;
|
: neg? 0 < ;
|
||||||
: zero? 0 = ;
|
: zero? 0 = ;
|
||||||
|
@ -97,13 +95,10 @@
|
||||||
if source else drop then
|
if source else drop then
|
||||||
;
|
;
|
||||||
|
|
||||||
: << [ ;
|
: getattr (x 'fieldname -- field) swap 2 ->list builtins.getattr ;
|
||||||
: >>@ ] @@ ;
|
: .!! (obj args method-name -- result) tbm getattr !! ;
|
||||||
: >>! ] @@ [] swap !! ;
|
|
||||||
|
|
||||||
"string.sf" source
|
"string.sf" source
|
||||||
"list.sf" source
|
"list.sf" source
|
||||||
|
|
||||||
"init.sf" source-if-exists
|
"init.sf" source-if-exists
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from inspect import isfunction, isbuiltin
|
from inspect import isfunction, isbuiltin
|
||||||
import importlib
|
import importlib
|
||||||
|
import os
|
||||||
from compiler import Compiler
|
from compiler import Compiler
|
||||||
from arglist import Arglist
|
from arglist import Arglist
|
||||||
|
|
||||||
|
@ -16,8 +17,11 @@ def const_f(value):
|
||||||
def native_function_handler(func):
|
def native_function_handler(func):
|
||||||
def handle(forth, i):
|
def handle(forth, i):
|
||||||
args = forth.stack.pop()
|
args = forth.stack.pop()
|
||||||
|
#print(f"Native fun, calling {func}({args})")
|
||||||
result = func(*args)
|
result = func(*args)
|
||||||
|
#print(f'Result: {result}')
|
||||||
forth.stack.push(result)
|
forth.stack.push(result)
|
||||||
|
#print("pushed result")
|
||||||
return i + 1
|
return i + 1
|
||||||
return handle
|
return handle
|
||||||
|
|
||||||
|
@ -35,6 +39,11 @@ def import_native_module(forth, m, alias=None, excludes=[]):
|
||||||
else:
|
else:
|
||||||
forth.namespace[localname] = const_f(val)
|
forth.namespace[localname] = const_f(val)
|
||||||
|
|
||||||
|
def w_eval(f, i):
|
||||||
|
token = f.stack.pop()
|
||||||
|
f.execute_token(token)
|
||||||
|
return i+1
|
||||||
|
|
||||||
def w_no_op(f, i):
|
def w_no_op(f, i):
|
||||||
return i+1
|
return i+1
|
||||||
|
|
||||||
|
@ -74,11 +83,36 @@ def w_require(f, i):
|
||||||
import_native_module(f, m, name)
|
import_native_module(f, m, name)
|
||||||
return i + 1
|
return i + 1
|
||||||
|
|
||||||
|
def source(f, path):
|
||||||
|
old_source_f = f.namespace.get('*source*', None)
|
||||||
|
old_namespace = f.namespace
|
||||||
|
try:
|
||||||
|
f.execute_file(path)
|
||||||
|
finally:
|
||||||
|
f.namespace['*source*'] = old_source_f
|
||||||
|
f.namespace = old_namespace
|
||||||
|
|
||||||
|
def w_load(f, i):
|
||||||
|
path = f.stack.pop()
|
||||||
|
source(f, path)
|
||||||
|
return i + 1
|
||||||
|
|
||||||
def w_source(f, i):
|
def w_source(f, i):
|
||||||
path = f.stack.pop()
|
path = f.stack.pop()
|
||||||
f.execute_file(path)
|
if os.path.isabs(path):
|
||||||
|
source(f, path)
|
||||||
return i+1
|
return i+1
|
||||||
|
|
||||||
|
relative_dir = os.path.dirname(f.evaluate_token('*source*'))
|
||||||
|
relative_path = f'{relative_dir}/{path}'
|
||||||
|
if os.path.exists(relative_path):
|
||||||
|
source(f, relative_path)
|
||||||
|
return i+1
|
||||||
|
|
||||||
|
source(f, path)
|
||||||
|
return i+1
|
||||||
|
|
||||||
|
|
||||||
def execute_f(name, instructions):
|
def execute_f(name, instructions):
|
||||||
#print('execute_f:', name, len(instructions))
|
#print('execute_f:', name, len(instructions))
|
||||||
def inner(forth, i, debug=False):
|
def inner(forth, i, debug=False):
|
||||||
|
@ -140,6 +174,43 @@ def w_unique(f, ip): # pushes a uique object.
|
||||||
f.stack.push(Unique())
|
f.stack.push(Unique())
|
||||||
return ip+1
|
return ip+1
|
||||||
|
|
||||||
|
def w_map(f, ip):
|
||||||
|
l = f.stack.pop()
|
||||||
|
word = f.stack.pop()
|
||||||
|
|
||||||
|
word_f = f.namespace.get(word, None)
|
||||||
|
result = []
|
||||||
|
|
||||||
|
for item in l:
|
||||||
|
f.stack.push(item)
|
||||||
|
word_f(f, 0)
|
||||||
|
result.append(f.stack.pop())
|
||||||
|
|
||||||
|
f.stack.push(result)
|
||||||
|
return ip+1
|
||||||
|
|
||||||
|
def w_reduce(f, ip):
|
||||||
|
l = f.stack.pop()
|
||||||
|
word = f.stack.pop()
|
||||||
|
|
||||||
|
word_f = f.namespace.get(word, None)
|
||||||
|
|
||||||
|
if len(l) <= 0:
|
||||||
|
f.stack.push(None)
|
||||||
|
elif len(l) == 1:
|
||||||
|
f.stack.push(l[0])
|
||||||
|
else:
|
||||||
|
result = l[0]
|
||||||
|
l = l[1::-1]
|
||||||
|
for item in l:
|
||||||
|
f.stack.push(result)
|
||||||
|
f.stack.push(item)
|
||||||
|
word_f(f, 0)
|
||||||
|
result = f.stack.pop()
|
||||||
|
f.stack.push(result)
|
||||||
|
|
||||||
|
return ip+1
|
||||||
|
|
||||||
def w_bounded_list(f, ip):
|
def w_bounded_list(f, ip):
|
||||||
"""Create a list from delimted values on the stack.
|
"""Create a list from delimted values on the stack.
|
||||||
[list]
|
[list]
|
||||||
|
@ -168,34 +239,17 @@ def w_list(f, ip): # ->list
|
||||||
f.stack.push(l)
|
f.stack.push(l)
|
||||||
return ip+1
|
return ip+1
|
||||||
|
|
||||||
def qqw_lookup(f, i): # @@
|
def w_thread(f, i): # @@
|
||||||
l = f.stack.pop()
|
contents = f.stack.pop()
|
||||||
value = l[0]
|
result = contents[0]
|
||||||
for field in l[1::]:
|
for field in contents[1::]:
|
||||||
value = getattr(value, field)
|
if isinstance(field, str) and hasattr(result, field):
|
||||||
f.stack.push(value)
|
result = getattr(result, field) # result.field
|
||||||
return i+1
|
|
||||||
|
|
||||||
def w_lookup(f, i): # ->
|
|
||||||
value = f.stack.pop()
|
|
||||||
fields = f.stack.pop()
|
|
||||||
print(f'value {value} fields {fields}')
|
|
||||||
|
|
||||||
if not isinstance(fields, list):
|
|
||||||
fields = [fields]
|
|
||||||
|
|
||||||
for field in fields:
|
|
||||||
print(f'value {value} field {field}')
|
|
||||||
if isinstance(field, str) and hasattr(value, field):
|
|
||||||
print("->getattr")
|
|
||||||
value = getattr(value, field)
|
|
||||||
elif isinstance(field, Arglist):
|
elif isinstance(field, Arglist):
|
||||||
print("->arglist")
|
result = result(*field) # result(*field)
|
||||||
value = value(*field)
|
|
||||||
else:
|
else:
|
||||||
print("index")
|
result = result[field] # result[field]
|
||||||
value = value[field]
|
f.stack.push(result)
|
||||||
f.stack.push(value)
|
|
||||||
return i+1
|
return i+1
|
||||||
|
|
||||||
|
|
||||||
|
@ -259,23 +313,6 @@ def w_getattribute(f, i):
|
||||||
f.stack.push(result)
|
f.stack.push(result)
|
||||||
return i+1
|
return i+1
|
||||||
|
|
||||||
def w_arrow(f, i): # ->
|
|
||||||
contents = f.stack.pop()
|
|
||||||
result = contents[0]
|
|
||||||
for field in contents[1::]:
|
|
||||||
print(f'result {result} field {field}')
|
|
||||||
if isinstance(field, str) and hasattr(result, field):
|
|
||||||
print("->getattr")
|
|
||||||
result = getattr(result, field)
|
|
||||||
elif isinstance(field, Arglist):
|
|
||||||
print("->arglist")
|
|
||||||
result = result(*field)
|
|
||||||
else:
|
|
||||||
print("index")
|
|
||||||
result = result[field]
|
|
||||||
f.stack.push(result)
|
|
||||||
return i+1
|
|
||||||
|
|
||||||
def w_def(f, i):
|
def w_def(f, i):
|
||||||
value = f.stack.pop()
|
value = f.stack.pop()
|
||||||
name = f.stack.pop()
|
name = f.stack.pop()
|
||||||
|
@ -351,6 +388,60 @@ def w_dup(f, i):
|
||||||
f.stack.push(x)
|
f.stack.push(x)
|
||||||
return i+1
|
return i+1
|
||||||
|
|
||||||
|
def w_tmb(f, i): # A noop
|
||||||
|
# t = f.stack.pop()
|
||||||
|
# m = f.stack.pop()
|
||||||
|
# b = f.stack.pop()
|
||||||
|
# f.stack.push(b)
|
||||||
|
# f.stack.push(m)
|
||||||
|
# f.stack.push(t)
|
||||||
|
return i+1
|
||||||
|
|
||||||
|
def w_tbm(f, i):
|
||||||
|
t = f.stack.pop()
|
||||||
|
m = f.stack.pop()
|
||||||
|
b = f.stack.pop()
|
||||||
|
f.stack.push(m)
|
||||||
|
f.stack.push(b)
|
||||||
|
f.stack.push(t)
|
||||||
|
return i+1
|
||||||
|
|
||||||
|
def w_bmt(f, i):
|
||||||
|
t = f.stack.pop()
|
||||||
|
m = f.stack.pop()
|
||||||
|
b = f.stack.pop()
|
||||||
|
f.stack.push(t)
|
||||||
|
f.stack.push(m)
|
||||||
|
f.stack.push(b)
|
||||||
|
return i+1
|
||||||
|
|
||||||
|
def w_btm(f, i):
|
||||||
|
t = f.stack.pop()
|
||||||
|
m = f.stack.pop()
|
||||||
|
b = f.stack.pop()
|
||||||
|
f.stack.push(m)
|
||||||
|
f.stack.push(t)
|
||||||
|
f.stack.push(b)
|
||||||
|
return i+1
|
||||||
|
|
||||||
|
def w_mtb(f, i):
|
||||||
|
t = f.stack.pop()
|
||||||
|
m = f.stack.pop()
|
||||||
|
b = f.stack.pop()
|
||||||
|
f.stack.push(b)
|
||||||
|
f.stack.push(t)
|
||||||
|
f.stack.push(m)
|
||||||
|
return i+1
|
||||||
|
|
||||||
|
def w_mbt(f, i):
|
||||||
|
t = f.stack.pop()
|
||||||
|
m = f.stack.pop()
|
||||||
|
b = f.stack.pop()
|
||||||
|
f.stack.push(t)
|
||||||
|
f.stack.push(b)
|
||||||
|
f.stack.push(m)
|
||||||
|
return i+1
|
||||||
|
|
||||||
def w_rot(f, i):
|
def w_rot(f, i):
|
||||||
c = f.stack.pop()
|
c = f.stack.pop()
|
||||||
b = f.stack.pop()
|
b = f.stack.pop()
|
||||||
|
|
Loading…
Reference in a new issue