python-plus-plus/ppp_stdlib.py
2024-10-01 14:37:23 +10:00

117 lines
3.7 KiB
Python

from typing import Callable, Dict, List, Tuple
from ppp_ast import Statements
from ppp_object import Bool, EnumValue, Int, Object, Function, Str, TypeObject, Void, List as ListObject
from ppp_types import Bool as BoolType, FunctionType, GenericType, Int as IntType, Str as StrType, Type, TypeType, VariableType, Void as VoidType, Object as ObjectType, ListType
def PythonFunction(name: str, parameters: List[Tuple[str, Type]], return_type: Type, func: Callable[..., Object]) -> Object:
return Function(FunctionType([parameter[1] for parameter in parameters], return_type), (name, parameters, return_type, Statements([]), lambda _0, _1, _2, _3, *args: func(*args)))
def print_impl(str_: Object) -> Object:
assert isinstance(str_, Str)
print(str_.str, end='')
return Void
Print = PythonFunction("print", [('string', StrType)], VoidType, print_impl)
def int_to_str_impl(int_: Object) -> Object:
assert isinstance(int_, Int)
return Str(str(int_.num))
IntToStr = PythonFunction("int_to_str", [('integer', IntType)], StrType, int_to_str_impl)
def debug_print_impl(obj: Object) -> Object:
print(obj)
return Void
DebugPrint = PythonFunction("debug_print", [('object', ObjectType)], VoidType, debug_print_impl)
def read_impl(str_: Object) -> Object:
assert isinstance(str_, Str)
with open(str_.str) as f: return Str(f.read())
Read = PythonFunction("read", [('file_path', StrType)], StrType, read_impl)
def len_impl(list_: Object) -> Object:
assert list_.get_type().is_indexable(), list_
match list_:
case Str(str): return Int(len(str))
case ListObject(_, list): return Int(len(list))
case _: assert False, ("Unimplemented", list_)
assert False
# TODO: Use polymorphism to make this work for both list<T> and str
Len = PythonFunction("len", [('list', ListType(VariableType("")))], IntType, len_impl)
def str_len_impl(str_: Object) -> Object:
assert isinstance(str_, Str)
return Int(len(str_.str))
StrLen = PythonFunction("strlen", [('string', StrType)], IntType, str_len_impl)
def str_to_int_impl(str_: Object) -> Object:
assert isinstance(str_, Str)
assert str_.str.isdigit()
return Int(int(str_.str))
StrToInt = PythonFunction("str_to_int", [('string', StrType)], IntType, str_to_int_impl)
def range_impl(start: Object, end: Object) -> Object:
assert isinstance(start, Int)
assert isinstance(end, Int)
return ListObject(ListType(IntType), [Int(i) for i in range(start.num, end.num)])
Range = PythonFunction("range", [('start', IntType), ('end', IntType)], ListType(IntType), range_impl)
def join_by_impl(seperator: Object, list: Object) -> Object:
assert isinstance(seperator, Str)
assert isinstance(list, ListObject)
if len(list.list) == 0: return Str("")
assert list.type.type.is_subtype_of(StrType), list
new_array: List[str] = []
for str_ in list.list:
assert isinstance(str_, Str)
new_array.append(str_.str)
return Str(seperator.str.join(new_array))
JoinBy = PythonFunction("join_by", [('seperator', StrType), ('list', ListType(StrType))], StrType, join_by_impl)
def id_impl(obj: Object) -> Object:
match obj:
case EnumValue(_, _, _): return Int(id(obj))
case _: assert False, ("Unimplemented", obj)
Id = PythonFunction("id", [('object', ObjectType)], IntType, id_impl)
StrTypeObj = TypeObject(StrType)
IntTypeObj = TypeObject(IntType)
VoidTypeObj = TypeObject(VoidType)
BoolTypeObj = TypeObject(BoolType)
True_ = Bool(True)
False_ = Bool(False)
NoneObj = Void
variables: Dict[str, Object] = {
'print': Print,
'true': True_,
'false': False_,
'int_to_str': IntToStr,
'str': StrTypeObj,
'int': IntTypeObj,
'bool': BoolTypeObj,
'void': VoidTypeObj,
'debug_print': DebugPrint,
'read': Read,
'len': Len,
'str_len': StrLen,
'str_to_int': StrToInt,
'none': NoneObj,
'range': Range,
'join_by': JoinBy,
'id': Id
}