Clean up attr resolution.

This commit is contained in:
Russ Olsen 2020-04-23 09:10:27 -04:00
parent 965f78f142
commit a4e2a1997a
5 changed files with 164 additions and 77 deletions

View file

@ -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 ;

View file

@ -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")

View file

@ -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

View file

@ -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 ;
@ -84,26 +81,24 @@
: p . nl ; : p . nl ;
: top dup p ; : top dup p ;
: -- -1 + ; : -- -1 + ;
: ++ 1 + ; : ++ 1 + ;
: *2 2 * ;
: pos? 0 > ; : pos? 0 > ;
: neg? 0 < ; : neg? 0 < ;
: zero? 0 = ; : zero? 0 = ;
: source-if-exists : source-if-exists
(path --) (path --)
dup dup
1 ->list os.path.exists 1 ->list os.path.exists
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

View file

@ -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,10 +83,35 @@ 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):
return i + 1 source(f, path)
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))
@ -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()