mirror of
https://github.com/russolsen/sallyforth
synced 2024-12-25 21:58:18 +01:00
Added basic namespace support.
This commit is contained in:
parent
8d4375dbf1
commit
f10edf9fd7
7 changed files with 236 additions and 57 deletions
2
sallyforth/arglist.py
Normal file
2
sallyforth/arglist.py
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
class Arglist(list):
|
||||||
|
pass
|
|
@ -4,6 +4,7 @@ from words import *
|
||||||
import words
|
import words
|
||||||
from lex import forth_prompt, read_tokens, is_string, tokenize
|
from lex import forth_prompt, read_tokens, is_string, tokenize
|
||||||
from stack import Stack
|
from stack import Stack
|
||||||
|
from namespace import Namespace
|
||||||
|
|
||||||
def to_number(token):
|
def to_number(token):
|
||||||
try:
|
try:
|
||||||
|
@ -17,31 +18,33 @@ def to_number(token):
|
||||||
class Forth:
|
class Forth:
|
||||||
def __init__(self, startup=None):
|
def __init__(self, startup=None):
|
||||||
self.stack = Stack()
|
self.stack = Stack()
|
||||||
self.dictionary = {
|
self.namespaces = {}
|
||||||
|
initial_defs = {
|
||||||
'*prompt*': const_f('SallyForth>> '),
|
'*prompt*': const_f('SallyForth>> '),
|
||||||
'true': const_f(True),
|
'true': const_f(True),
|
||||||
'false': const_f(False),
|
'false': const_f(False),
|
||||||
'nil': const_f(None),
|
'nil': const_f(None),
|
||||||
'0': const_f(0),
|
'0': const_f(0),
|
||||||
'1': const_f(1),
|
'1': const_f(1),
|
||||||
'2': const_f(2) }
|
'2': const_f(2)}
|
||||||
|
|
||||||
self.import_from_module(words, 'w_')
|
self.forth_ns = self.make_namespace('forth', initial_defs)
|
||||||
|
user_ns = self.make_namespace('user', {}, [self.forth_ns])
|
||||||
|
|
||||||
|
self.forth_ns.import_from_module(words, 'w_')
|
||||||
|
self.namespace = self.forth_ns
|
||||||
|
|
||||||
self.compiler = None
|
self.compiler = None
|
||||||
if startup:
|
|
||||||
execute_startup(startup)
|
|
||||||
|
|
||||||
def import_from_module(self, m, prefix):
|
self.defvar("argv", sys.argv[1::])
|
||||||
names = dir(m)
|
|
||||||
prefix_len = len(prefix)
|
if startup:
|
||||||
for name in names:
|
self.execute_file(startup)
|
||||||
if name.startswith(prefix):
|
|
||||||
word_name = name[prefix_len::]
|
self.namespace = user_ns
|
||||||
self.dictionary[word_name] = m.__getattribute__(name)
|
|
||||||
|
|
||||||
def defvar(self, name, value):
|
def defvar(self, name, value):
|
||||||
self.dictionary[name] = const_f(value)
|
self.namespace[name] = const_f(value)
|
||||||
|
|
||||||
def evaluate_token(self, token):
|
def evaluate_token(self, token):
|
||||||
self.execute_token(token)
|
self.execute_token(token)
|
||||||
|
@ -62,8 +65,22 @@ class Forth:
|
||||||
else:
|
else:
|
||||||
self.compile_token(token)
|
self.compile_token(token)
|
||||||
|
|
||||||
|
def set_ns(self, ns_name):
|
||||||
|
if ns_name in self.namespaces:
|
||||||
|
self.namespace = self.namespaces[ns_name]
|
||||||
|
else:
|
||||||
|
raise ValueError(f'No such namespace: {ns_name}')
|
||||||
|
|
||||||
|
def make_namespace(self, ns_name, initial_defs={}, refers=[]):
|
||||||
|
print(f'New namespace {ns_name} {refers}')
|
||||||
|
result = Namespace(ns_name, initial_defs, refers)
|
||||||
|
self.namespaces[ns_name] = result
|
||||||
|
print(f'Returning {result}')
|
||||||
|
return result
|
||||||
|
|
||||||
def execute_file(self, fpath):
|
def execute_file(self, fpath):
|
||||||
old_source = self.dictionary.get('*source*', None)
|
old_source = self.namespace.get('*source*', None)
|
||||||
|
old_namespace = self.namespace
|
||||||
self.defvar('*source*', fpath)
|
self.defvar('*source*', fpath)
|
||||||
with open(fpath) as f:
|
with open(fpath) as f:
|
||||||
line = f.readline()
|
line = f.readline()
|
||||||
|
@ -71,8 +88,8 @@ class Forth:
|
||||||
tokens = tokenize(line)
|
tokens = tokenize(line)
|
||||||
self.execute_tokens(tokens)
|
self.execute_tokens(tokens)
|
||||||
line = f.readline()
|
line = f.readline()
|
||||||
self.defvar('*source*', '')
|
self.namespace['*source*'] = old_source
|
||||||
self.dictionary['*source*'] = old_source
|
self.namespace = old_namespace
|
||||||
|
|
||||||
def compile_token(self, token):
|
def compile_token(self, token):
|
||||||
if self.compiler.name == None:
|
if self.compiler.name == None:
|
||||||
|
@ -83,28 +100,29 @@ class Forth:
|
||||||
self.compiler.add_instruction(const_f(token[1::]))
|
self.compiler.add_instruction(const_f(token[1::]))
|
||||||
return
|
return
|
||||||
|
|
||||||
if token in self.dictionary:
|
if token in self.namespace:
|
||||||
word = self.dictionary[token]
|
word = self.namespace[token]
|
||||||
if 'immediate' in word.__dict__:
|
if 'immediate' in word.__dict__:
|
||||||
word(self, 0)
|
word(self, 0)
|
||||||
else:
|
else:
|
||||||
self.compiler.add_instruction(self.dictionary[token])
|
self.compiler.add_instruction(self.namespace[token])
|
||||||
return
|
return
|
||||||
|
|
||||||
n = to_number(token)
|
n = to_number(token)
|
||||||
if n == None:
|
if n == None:
|
||||||
|
print(f'{token}? Compile of {self.compiler.name} terminated.')
|
||||||
self.compiler = None
|
self.compiler = None
|
||||||
print(f'{token}? Compile terminated.')
|
|
||||||
else:
|
else:
|
||||||
self.compiler.add_instruction(const_f(n))
|
self.compiler.add_instruction(const_f(n))
|
||||||
|
|
||||||
def execute_token(self, token):
|
def execute_token(self, token):
|
||||||
|
# print("x token:", token)
|
||||||
if is_string(token):
|
if is_string(token):
|
||||||
self.stack.push(token[1::])
|
self.stack.push(token[1::])
|
||||||
return
|
return
|
||||||
|
|
||||||
if token in self.dictionary:
|
if token in self.namespace:
|
||||||
self.dictionary[token](self, 0)
|
self.namespace[token](self, 0)
|
||||||
return
|
return
|
||||||
|
|
||||||
n = to_number(token)
|
n = to_number(token)
|
||||||
|
@ -116,5 +134,5 @@ class Forth:
|
||||||
def dump(self):
|
def dump(self):
|
||||||
print('Forth:', self)
|
print('Forth:', self)
|
||||||
print('Stack:', self.stack)
|
print('Stack:', self.stack)
|
||||||
print('Dictionary:', self.dictionary)
|
print('Dictionary:', self.namespace)
|
||||||
print('Compiler:', self.compiler)
|
print('Compiler:', self.compiler)
|
||||||
|
|
86
sallyforth/namespace.py
Normal file
86
sallyforth/namespace.py
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
class Namespace:
|
||||||
|
def __init__(self, name, initial_contents={}, refers=[]):
|
||||||
|
print('name', name)
|
||||||
|
print('initial contents', initial_contents)
|
||||||
|
print('refers', refers)
|
||||||
|
print('===')
|
||||||
|
self.name = name
|
||||||
|
self.contents = initial_contents.copy()
|
||||||
|
self.refers = refers.copy()
|
||||||
|
|
||||||
|
def refer(self, ns):
|
||||||
|
"""
|
||||||
|
Add the supplied namespace to the refers list.
|
||||||
|
"""
|
||||||
|
self.refers.append(ns)
|
||||||
|
|
||||||
|
def import_from_module(self, m, prefix):
|
||||||
|
"""
|
||||||
|
Import all of the word defining functions in
|
||||||
|
module m whose function names start with prefix
|
||||||
|
into this namespace. Removes the prefix.
|
||||||
|
"""
|
||||||
|
names = dir(m)
|
||||||
|
prefix_len = len(prefix)
|
||||||
|
for name in names:
|
||||||
|
if name.startswith(prefix):
|
||||||
|
word_name = name[prefix_len::]
|
||||||
|
self[word_name] = m.__getattribute__(name)
|
||||||
|
|
||||||
|
def keys(self):
|
||||||
|
return self.contents.keys()
|
||||||
|
|
||||||
|
def all_keys(self):
|
||||||
|
result = set(self.contents.keys())
|
||||||
|
for r in self.refers:
|
||||||
|
result = result.union(set(r.contents.keys()))
|
||||||
|
return result
|
||||||
|
|
||||||
|
def get(self, key, default):
|
||||||
|
if not self.__contains__(key):
|
||||||
|
return default
|
||||||
|
return self[key]
|
||||||
|
|
||||||
|
def __contains__(self, key):
|
||||||
|
if self.contents.__contains__(key):
|
||||||
|
return True
|
||||||
|
for r in self.refers:
|
||||||
|
if r.__contains__(key):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def local_contains(self, key):
|
||||||
|
return self.contents.__contains__(key)
|
||||||
|
|
||||||
|
def __delattr__(self, key):
|
||||||
|
return self.contents.__delattr__(key)
|
||||||
|
|
||||||
|
def __setitem__(self, key, x):
|
||||||
|
self.contents[key] = x
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self.contents.__iter__()
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
# print("get item", key, self.contents)
|
||||||
|
if key in self.contents:
|
||||||
|
return self.contents[key]
|
||||||
|
# print("not in local ns")
|
||||||
|
for imp in self.refers:
|
||||||
|
# print("trying ", imp)
|
||||||
|
if key in imp:
|
||||||
|
return imp[key]
|
||||||
|
# print("not found")
|
||||||
|
raise KeyError(key)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'Namespace({self.name})'
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print("main program")
|
||||||
|
x = Namespace('x', {'a': 1, 'b': 2})
|
||||||
|
print(x['a'])
|
||||||
|
y = Namespace('y', {'c': 3, 'd': 4})
|
||||||
|
print(y['c'])
|
||||||
|
y.refer(x)
|
||||||
|
print(y['a'])
|
|
@ -4,6 +4,7 @@ import atexit
|
||||||
from kernel import Forth
|
from kernel import Forth
|
||||||
from lex import tokenize
|
from lex import tokenize
|
||||||
import readline
|
import readline
|
||||||
|
import traceback
|
||||||
|
|
||||||
HistoryFile=".sallyforth"
|
HistoryFile=".sallyforth"
|
||||||
|
|
||||||
|
@ -13,7 +14,7 @@ class Completer:
|
||||||
def __init__(self, f):
|
def __init__(self, f):
|
||||||
self.f = f
|
self.f = f
|
||||||
def complete(self, prefix, index):
|
def complete(self, prefix, index):
|
||||||
self.matching_words = [w for w in self.f.dictionary.keys() if w.startswith(prefix) ]
|
self.matching_words = [w for w in self.f.namespace.all_keys() if w.startswith(prefix) ]
|
||||||
try:
|
try:
|
||||||
return self.matching_words[index]
|
return self.matching_words[index]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
|
@ -32,14 +33,14 @@ def setup_readline(history_path, f):
|
||||||
atexit.register(save_history)
|
atexit.register(save_history)
|
||||||
|
|
||||||
def setup_forth():
|
def setup_forth():
|
||||||
f = Forth()
|
|
||||||
f.defvar("argv", sys.argv[1::])
|
|
||||||
|
|
||||||
source_dir = os.path.dirname(os.path.abspath(__file__))
|
source_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
startup_file = f'{source_dir}/startup.sf'
|
startup_file = f'{source_dir}/startup.sf'
|
||||||
|
|
||||||
if os.path.exists(startup_file):
|
if os.path.exists(startup_file):
|
||||||
f.execute_file(startup_file)
|
f = Forth(startup_file)
|
||||||
|
else:
|
||||||
|
f = Forth()
|
||||||
|
|
||||||
|
|
||||||
return f
|
return f
|
||||||
|
|
||||||
|
@ -62,6 +63,7 @@ def repl(f):
|
||||||
print("Error:", exc_type)
|
print("Error:", exc_type)
|
||||||
print("Error:", exc_value)
|
print("Error:", exc_value)
|
||||||
print("Error:", exc_traceback)
|
print("Error:", exc_traceback)
|
||||||
|
traceback.print_tb(exc_traceback)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -18,6 +18,10 @@ class Stack:
|
||||||
self.top = -1;
|
self.top = -1;
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
for i in range(self.top, -1, -1):
|
||||||
|
yield self.stack[i]
|
||||||
|
|
||||||
def peek(self):
|
def peek(self):
|
||||||
return self.stack[self.top]
|
return self.stack[self.top]
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
'semi '; alias
|
'semi '; alias
|
||||||
'bounded_list '[list] alias
|
'bounded_list '[list] alias
|
||||||
'list '->list alias
|
'list '->list alias
|
||||||
|
'to_arglist '->arglist alias
|
||||||
'list_to_map 'list->map alias
|
'list_to_map 'list->map alias
|
||||||
'lookup '@@ alias
|
'lookup '@@ alias
|
||||||
'call '!! alias
|
'call '!! alias
|
||||||
|
@ -29,6 +30,7 @@
|
||||||
'le '<= alias
|
'le '<= alias
|
||||||
'ge '>= alias
|
'ge '>= alias
|
||||||
'eq '= alias
|
'eq '= alias
|
||||||
|
'current_ns '*ns* alias
|
||||||
|
|
||||||
: *prompt* "Sally> " ;
|
: *prompt* "Sally> " ;
|
||||||
|
|
||||||
|
@ -54,18 +56,25 @@
|
||||||
|
|
||||||
: {{}} ( -- <empty set>) {{ }} ;
|
: {{}} ( -- <empty set>) {{ }} ;
|
||||||
|
|
||||||
: type (x -- type-of-x) 1 ->list builtins.type !! ;
|
: [: [ ;
|
||||||
|
: :] ] ->arglist ;
|
||||||
|
|
||||||
: px0 (mod fname -- result) [] px ;
|
: => [ ;
|
||||||
: px1 (mod fname arg -- result) 1 ->list px ;
|
: >! ] arrow ;
|
||||||
: px2 (mod fname arg arg -- result) 2 ->list px ;
|
|
||||||
: px3 (mod fname arg arg arg -- result) 3 ->list px ;
|
: <. [ ;
|
||||||
|
: .> ] arrow ;
|
||||||
|
|
||||||
|
: !!0 [] swap call ;
|
||||||
|
|
||||||
|
: type 1 ->list builtins.type !! ;
|
||||||
|
|
||||||
: dir (mod -- keys) "dir" px0 ;
|
|
||||||
: ctime [] time.ctime ;
|
: ctime [] time.ctime ;
|
||||||
: sleep 1 ->list stack time.sleep drop ;
|
: sleep 1 ->list stack time.sleep drop ;
|
||||||
|
|
||||||
: hello (simple greeting) "Hello" . nl ;
|
: callable? 1 ->list builtins.callable ;
|
||||||
|
|
||||||
|
: hello "Hello" . nl ;
|
||||||
|
|
||||||
: >0 0 > ;
|
: >0 0 > ;
|
||||||
: <0 0 < ;
|
: <0 0 < ;
|
||||||
|
@ -75,20 +84,22 @@
|
||||||
: p . nl ;
|
: p . nl ;
|
||||||
: top dup p ;
|
: top dup p ;
|
||||||
|
|
||||||
: -- ( n -- n-1 ) -1 + ;
|
: -- -1 + ;
|
||||||
: ++ ( n -- n+1 ) 1 + ;
|
: ++ 1 + ;
|
||||||
: pos? (n -- bool) 0 > ;
|
: pos? 0 > ;
|
||||||
: neg? (n -- bool) 0 < ;
|
: neg? 0 < ;
|
||||||
: zero? (n -- bool) 0 = ;
|
: zero? 0 = ;
|
||||||
|
|
||||||
: source-if-exists (path --)
|
: source-if-exists
|
||||||
|
(path --)
|
||||||
dup
|
dup
|
||||||
1 ->list os.path.exists
|
1 ->list os.path.exists
|
||||||
if source else drop then
|
if source else drop then
|
||||||
;
|
;
|
||||||
|
|
||||||
: << [ ;
|
: << [ ;
|
||||||
: >> ] @@ ;
|
: >>@ ] @@ ;
|
||||||
|
: >>! ] @@ [] swap !! ;
|
||||||
|
|
||||||
"init.sf" source-if-exists
|
"init.sf" source-if-exists
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from compiler import Compiler
|
|
||||||
import importlib
|
|
||||||
from inspect import isfunction, isbuiltin
|
from inspect import isfunction, isbuiltin
|
||||||
|
import importlib
|
||||||
|
from compiler import Compiler
|
||||||
|
from arglist import Arglist
|
||||||
|
|
||||||
class Unique:
|
class Unique:
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -30,18 +31,31 @@ def import_native_module(forth, m, alias=None, excludes=[]):
|
||||||
#print(localname)
|
#print(localname)
|
||||||
val = m.__getattribute__(name)
|
val = m.__getattribute__(name)
|
||||||
if isfunction(val) or isbuiltin(val):
|
if isfunction(val) or isbuiltin(val):
|
||||||
forth.dictionary[localname] = native_function_handler(val)
|
forth.namespace[localname] = native_function_handler(val)
|
||||||
else:
|
else:
|
||||||
forth.dictionary[localname] = const_f(val)
|
forth.namespace[localname] = const_f(val)
|
||||||
|
|
||||||
def w_forth(f, i):
|
def w_forth(f, i):
|
||||||
f.stack.push(f)
|
f.stack.push(f)
|
||||||
return i+1
|
return i+1
|
||||||
|
|
||||||
|
def w_current_ns(f, i):
|
||||||
|
f.stack.push(f.namespace)
|
||||||
|
return i + 1
|
||||||
|
|
||||||
|
def w_ns(f, i):
|
||||||
|
name = f.stack.pop()
|
||||||
|
if name in f.namespaces:
|
||||||
|
f.namespace = f.namespaces[name]
|
||||||
|
else:
|
||||||
|
new_ns = f.make_namespace(name, {}, [f.forth_ns])
|
||||||
|
f.namespace = new_ns
|
||||||
|
return i + 1
|
||||||
|
|
||||||
def w_alias(f, i):
|
def w_alias(f, i):
|
||||||
new_name = f.stack.pop()
|
new_name = f.stack.pop()
|
||||||
old_name = f.stack.pop()
|
old_name = f.stack.pop()
|
||||||
f.dictionary[new_name] = f.dictionary[old_name]
|
f.namespace[new_name] = f.namespace[old_name]
|
||||||
return i + 1
|
return i + 1
|
||||||
|
|
||||||
def w_require(f, i):
|
def w_require(f, i):
|
||||||
|
@ -91,7 +105,7 @@ def w_recur(f, i):
|
||||||
def w_import(f, i):
|
def w_import(f, i):
|
||||||
name = f.stack.pop()
|
name = f.stack.pop()
|
||||||
m = importlib.import_module(name)
|
m = importlib.import_module(name)
|
||||||
f.dictionary[name] = const_f(m)
|
f.namespace[name] = const_f(m)
|
||||||
return i+1
|
return i+1
|
||||||
|
|
||||||
def w_call(f, i):
|
def w_call(f, i):
|
||||||
|
@ -105,15 +119,10 @@ def w_call(f, i):
|
||||||
|
|
||||||
def w_px(f, i):
|
def w_px(f, i):
|
||||||
args = f.stack.pop()
|
args = f.stack.pop()
|
||||||
#print('args', args)
|
|
||||||
name = f.stack.pop()
|
name = f.stack.pop()
|
||||||
#print('name', name)
|
|
||||||
m = f.stack.pop()
|
m = f.stack.pop()
|
||||||
#print('mod:', m)
|
|
||||||
func = m.__dict__[name]
|
func = m.__dict__[name]
|
||||||
#print('f:', f);
|
|
||||||
result = func(*args)
|
result = func(*args)
|
||||||
#print('result', result)
|
|
||||||
f.stack.push(result)
|
f.stack.push(result)
|
||||||
return i+1
|
return i+1
|
||||||
|
|
||||||
|
@ -136,16 +145,20 @@ def w_bounded_list(f, ip):
|
||||||
f.stack.push(l)
|
f.stack.push(l)
|
||||||
return ip+1
|
return ip+1
|
||||||
|
|
||||||
|
def w_to_arglist(f, ip):
|
||||||
|
l = f.stack.pop()
|
||||||
|
f.stack.push(Arglist(l))
|
||||||
|
return ip+1
|
||||||
|
|
||||||
def w_list(f, ip): # ->list
|
def w_list(f, ip): # ->list
|
||||||
n = f.stack.pop()
|
n = f.stack.pop()
|
||||||
l = []
|
l = []
|
||||||
for i in range(n):
|
for i in range(n):
|
||||||
l.append(f.stack.pop())
|
l.append(f.stack.pop())
|
||||||
#print(l)
|
|
||||||
f.stack.push(l)
|
f.stack.push(l)
|
||||||
return ip+1
|
return ip+1
|
||||||
|
|
||||||
def w_lookup(f, i): # @@
|
def qqw_lookup(f, i): # @@
|
||||||
l = f.stack.pop()
|
l = f.stack.pop()
|
||||||
value = l[0]
|
value = l[0]
|
||||||
for field in l[1::]:
|
for field in l[1::]:
|
||||||
|
@ -153,6 +166,29 @@ def w_lookup(f, i): # @@
|
||||||
f.stack.push(value)
|
f.stack.push(value)
|
||||||
return i+1
|
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):
|
||||||
|
print("->arglist")
|
||||||
|
value = value(*field)
|
||||||
|
else:
|
||||||
|
print("index")
|
||||||
|
value = value[field]
|
||||||
|
f.stack.push(value)
|
||||||
|
return i+1
|
||||||
|
|
||||||
|
|
||||||
ListMarker = object()
|
ListMarker = object()
|
||||||
|
|
||||||
def w_startlist(f, i): # [
|
def w_startlist(f, i): # [
|
||||||
|
@ -213,6 +249,23 @@ 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()
|
||||||
|
@ -322,7 +375,7 @@ def w_semi(forth, i):
|
||||||
forth.compiler.add_instruction(w_return)
|
forth.compiler.add_instruction(w_return)
|
||||||
name = forth.compiler.name
|
name = forth.compiler.name
|
||||||
word_f = execute_f(name, forth.compiler.instructions)
|
word_f = execute_f(name, forth.compiler.instructions)
|
||||||
forth.dictionary[name] = word_f
|
forth.namespace[name] = word_f
|
||||||
forth.compiler = None
|
forth.compiler = None
|
||||||
return i+1
|
return i+1
|
||||||
|
|
||||||
|
@ -419,5 +472,8 @@ def w_idump(f, i):
|
||||||
w_idump.__dict__['immediate'] = True
|
w_idump.__dict__['immediate'] = True
|
||||||
|
|
||||||
def w_stack(f, i):
|
def w_stack(f, i):
|
||||||
print(f'Stack: <B[{f.stack}]T>')
|
print("::top::")
|
||||||
|
for x in f.stack:
|
||||||
|
print(f'{x}')
|
||||||
|
print("::bottom::")
|
||||||
return i+1
|
return i+1
|
||||||
|
|
Loading…
Reference in a new issue