archivesOfToyLang/tshunhue/中秋節相關東西/__init__.py

156 lines
No EOL
4.7 KiB
Python

#!/usr/bin/env python3
import tokenizer
import parser
import sys
import collections
# path = sys.argv[1]
path = 'a.scm'
f = open(path, 'r')
file_content = "".join(f.readlines())
tokenized_content = tokenizer.tokenize(file_content)
parser = parser.Parser()
raw_ast = parser.parse(tokenized_content)
'''
Type inferencing
'''
ASTItemToken = collections.namedtuple('Node', ['content', 'type','free_var'])
def generate_empty_ast_token(ls):
kind = ""
free_var = []
if isinstance(ls,list):
content = [generate_empty_ast_token(i) for i in ls]
return ASTItemToken(content=content, type=kind, free_var=free_var)
else:
return ASTItemToken(content=ls, type=kind, free_var=free_var)
to_check_if_double_defined_ast = generate_empty_ast_token(raw_ast)
'''
data type list (Non-Closure or void):
[
(Type_name, Parent_Type, Detail)
Parent_type: if it's not subtype, the value is None.
Detail: Type detail of type [record or union] ["record", {"a": "int", "b": "dou"}] or None
]
'''
type_ls = [
("p_int","int",None),
("n_int", "int", None),
("z_int", "int", None),
("int", None, None),
("dou", None, None),
("str", None, None),
]
'''
var_and_type_list
'''
var_and_type_list = [
("%+", ("case", [
("->", ("p_int", "p_int"), "p_int"),
("->", ("n_int", "n_int"), "n_int"),
("->", ("p_int", "n_int"), "int"),
("->", ("n_int", "p_int"), "int"),
("->", ("int", "int"), "int"),
("->", ("dou", "dou"), "dou")
])
)
]
vars_ls = [{'defined' : {'%+', '%p'}, 'used' : {}}]
'''
check if there are any double defined variable
'''
def find_if_double_defined(ast, vars_ls):
if isinstance(ast.content,list):
for item in ast:
vars_ls = find_if_double_defined_aux(item, vars_ls)
return vars_ls
else:
return find_if_double_defined_aux(ast, vars_ls)
def find_if_double_defined_aux(ast, vars_ls):
if isinstance(ast.content,list):
ast_head = ast.content[0]
# define variable
if ast_head.val == 'define':
var_name = ast.content[1].val
current_variable_frame = vars_ls[-1]
if var_name in current_variable_frame['defined'] or var_name in current_variable_frame['used']:
raise Exception("variable double defined at ln %d, col %d" % (ast_head.line, ast_head.column))
else:
vars_ls[-1]['defined'].add(var_name) # add the new-defined to the list
rhs_var_ls = find_if_double_defined_aux(ast.content[3], vars_ls)
return vars_ls
# lambda
if ast_head.val == 'lambda':
orig_vars_ls = vars_ls
extended_vars_ls = vars_ls + [{'defined' : {}, 'used' : {}}]
# (lambda ((y int) ...)
if isinstance(ast.content[1].content, list):
arg_list = map(lambda x : x.content[0], ast.content[1].content)
# lambda (y ...)
else:
arg_list = map(lambda x : x.content, ast.content[1].content)
for arg in arg_list:
arg_name = arg.val
line = arg.line
column = arg.column
if arg_name in extended_vars_ls[-1]['defined']:
raise Exception("variable double defined at ln %d, col %d" % (line, column))
else:
extended_vars_ls[-1]['defined'].add(arg_name)
# after adding arguments, visit lambda body
for item in ast.content[2:]:
extended_vars_ls = find_if_double_defined_aux(item, extended_vars_ls)
# return orig_vars_ls, don't pollute it.
return orig_vars_ls
# function applying or basic operator, visiting all items
else:
for item in ast.content:
vars_ls = find_if_double_defined_aux(item, vars_ls)
return vars_ls
# variable or constant
else:
if ast.type in ['SYMBOL', 'OP']:
vars_ls[-1]['used'].add(arg_name)
else:
pass
return vars_ls
to_be_typeinferenced_ast = find_if_double_defined(to_check_if_double_defined_ast, vars_ls)
'''
TODO: 型別推測
def typeinfer(ast, type_ls, var_type_ls):
if isinstance(ast.content,list):
return [typeinfer_aux(ast, type_ls, var_type_ls) for i in ast]
else:
return typeinfer_aux(ast, type_ls, var_type_ls)
def typeinfer_aux(ast, type_ls, var):
if isinstance(ast.content, list):
list_head = ast.content[0]
if list_head.content.val == 'define':
'''