Skip to content

Commit

Permalink
Made dictionaries more internal.
Browse files Browse the repository at this point in the history
  • Loading branch information
DevReaper0 committed Feb 19, 2022
1 parent a8cff5a commit 8d66ebd
Show file tree
Hide file tree
Showing 14 changed files with 365 additions and 416 deletions.
21 changes: 13 additions & 8 deletions doc/41_dictionaries.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ lots of related variable names.
Here's an example of how to create a dictionary and assign
it to a variable.

`let names = Dictionary.new(['Jeffrey', 'Sam', 'Buddy'], ['Williams', 'Johnson', 'White']);`
`let names = ['Jeffrey': 'Williams', 'Sam': 'Johnson', 'Buddy': 'White'];`

The `names` dictionary holds three strings, each
representing a name.
Expand All @@ -22,11 +22,17 @@ for name in names {

Prints:
```
[Jeffrey, Williams]
[Sam, Johnson]
[Buddy, White]
['Jeffrey', 'Williams']
['Sam', 'Johnson']
['Buddy', 'White']
```

Creating an *empty* dictionary is a little different.
Here's an example of how to create an empty dictionary
and assign it to a variable.

`let names = [:];`

To access a specific item in a dictionary by index, use the
access operator (square brackets)

Expand All @@ -37,12 +43,11 @@ an object is contained by the dictionary, appending new items to
a dictionary, and more.

```javascript
names.contains('Buddy'); // false
names.containskey('Buddy'); // true
names.contains('Buddy'); // true

names.append(['Tiffany', 'Jones']); // names is now {'Jeffrey': 'Williams', 'Sam': 'Johnson', 'Buddy': 'White', 'Tiffany': 'Jones'}

names | Dict.new(['Sam', 'Johnson'], ['Tyler', 'Scotts']); // returns {'Jeffrey': 'Williams', 'Sam': 'Johnson', 'Buddy': 'White', 'Tyler': 'Scotts'}
names | ['Sam': 'Tyler', 'Johnson': 'Scotts']; // returns {'Jeffrey': 'Williams', 'Sam': 'Johnson', 'Buddy': 'White', 'Tyler': 'Scotts'}

names & Dict.new(['Sam', 'Johnson'], ['Tyler', 'Scotts']); // returns {'Sam': 'Johnson'}
names & ['Sam': 'Tyler', 'Johnson': 'Scotts']; // returns {'Sam': 'Johnson'}
```
18 changes: 16 additions & 2 deletions examples/python_methods.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
from interpreter.basic_value import BasicValue

# pyimport("examples/python_methods.py", "__testq__", "dictionaries");
# pyimport("examples/python_methods.py", "__testw__", "lists");

def dictionaries(arguments):
return BasicValue({"A": "B"})

def lists(arguments):
return BasicValue(["A", "B"])

def p(arguments):
print(arguments.arguments[0].extract_value())
return BasicValue(arguments.arguments[0].extract_value())
if len(arguments.arguments) > 0:
print(arguments.arguments[0].extract_value())
return BasicValue(arguments.arguments[0].extract_value())
print("Nothing provided.")
return BasicValue("Nothing provided.")

# Now just run:
# pyimport("examples/python_methods.py", "__p__", "p");
# pyimport("examples/python_methods.py", ["__p__"], ["p"]);
# pyimport("examples/python_methods.py", Dict.new(["__p__"], ["p"]));
# To add it to ParaCode
110 changes: 83 additions & 27 deletions interpreter/env/builtins.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from interpreter.typing.basic_type import BasicType
from interpreter.basic_object import BasicObject
from interpreter.basic_value import BasicValue
from interpreter.variable import VariableType
from interpreter.function import BuiltinFunction
from interpreter.env.builtin.arith import *
from interpreter.env.builtin.time import *
Expand Down Expand Up @@ -162,7 +163,9 @@ def builtin_array_len(arguments):
return BasicValue(len(arguments.arguments[0].extract_value()))

def builtin_dictionary_len(arguments):
return BasicValue(len(arguments.arguments[0][0].extract_value()))
if type(arguments.arguments[0].extract_value()) == dict:
return BasicValue(len(arguments.arguments[0].extract_value()))
return BasicValue(len(arguments.arguments[0].extract_value()[0]))

def builtin_array_set(arguments):
array = arguments.arguments[0].extract_value()
Expand All @@ -174,80 +177,109 @@ def builtin_array_set(arguments):
return BasicValue(array)

def builtin_dictionary_set(arguments):
array = arguments.arguments[0][0].extract_value()
index = arguments.arguments[0][1].extract_value()
value = arguments.arguments[0][2].extract_value()
dictionary = arguments.arguments[0].extract_value()
key = arguments.arguments[1].extract_value()
value = arguments.arguments[2].extract_value()

array[index] = value
dictionary[key] = value

return BasicValue(array)
return BasicValue(dictionary)

def builtin_array_clone(arguments):
array = arguments.arguments[0].extract_value()
new_array = array.copy()
return BasicValue(new_array)

def builtin_dictionary_clone(arguments):
array = arguments.arguments[0][0].extract_value()
new_array = array.copy()
return BasicValue(new_array)
dictionary = arguments.arguments[0].extract_value()
new_dictionary = dictionary.copy()
return BasicValue(new_dictionary)

def builtin_array_at(arguments):
obj = arguments.arguments[0].extract_value()
index = arguments.arguments[1].extract_value()

if index > len(obj):
# TODO make throw internal exception
# TODO throw internal exception
return BasicValue(None)

return BasicValue(obj[index])

def builtin_dictionary_at(arguments):
obj = arguments.arguments[0][0].extract_value()
index = arguments.arguments[0][1].extract_value()
obj = arguments.arguments[0].extract_value()
key = arguments.arguments[1].extract_value()

if key not in obj:
# TODO throw internal exception
return BasicValue(None)

return BasicValue(obj[key])

def builtin_dictionary_atindex(arguments):
obj = arguments.arguments[0].extract_value()
index = arguments.arguments[1].extract_value()

if index > len(obj):
# TODO make throw internal exception
# TODO throw internal exception
return BasicValue(None)

return BasicValue(obj[index])
return BasicValue([list(obj)[index], obj[list(obj)[index]]])

def builtin_dictionary_indexatkey(arguments):
obj = arguments.arguments[0].extract_value()
key = arguments.arguments[1].extract_value()

if key not in obj:
# TODO throw internal exception
return BasicValue(None)

return BasicValue(list(obj.keys()).index(key))

def builtin_dictionary_keys(arguments):
obj = arguments.arguments[0].extract_value()

return BasicValue(list(obj.keys()))

def builtin_dictionary_values(arguments):
obj = arguments.arguments[0].extract_value()

return BasicValue(list(obj.values()))

def builtin_dictionary_contains(arguments):
obj = arguments.arguments[0].extract_value()
key = arguments.arguments[1].extract_value()

return BasicValue(key in obj)

def builtin_array_append(arguments):
interpreter = arguments.interpreter
this_object = arguments.this_object

value_start = arguments.arguments[0]
value = arguments.arguments[0].extract_value()

value = value_start.extract_value()

if len(arguments.arguments) > 1:
for arg in arguments.arguments[1:]:
value.append(arg.extract_value())

return BasicValue(value)


def builtin_dictionary_append(arguments):
interpreter = arguments.interpreter
this_object = arguments.this_object

value_start = arguments.arguments[0][0]

value = value_start.extract_value()
value = arguments.arguments[0].extract_value()

if len(arguments.arguments[0]) > 1:
for arg in arguments.arguments[0][1:]:
value.append(arg.extract_value())
if len(arguments.arguments) > 1:
for arg in arguments.arguments[1:]:
value[arg.extract_value()[0]] = arg.extract_value()[1]

return BasicValue(value)

def builtin_str_append(arguments):
interpreter = arguments.interpreter
this_object = arguments.this_object

str_value_start = arguments.arguments[0]

str_value = str(str_value_start.extract_value())
str_value = str(arguments.arguments[0].extract_value())

if len(arguments.arguments) > 1:
for arg in arguments.arguments[1:]:
Expand Down Expand Up @@ -2622,3 +2654,27 @@ def builtin_macro_expand(arguments):
interpreter.visit(node)

return BasicValue(None)

def builtin_import_python(arguments):
interpreter = arguments.interpreter
this_object = arguments.this_object
node = arguments.node

# return BasicValue(exec((("from " + str(arguments.arguments[0].extract_value()).replace(".py", "").replace("/", ".") + " import *;") if str(arguments.arguments[0].extract_value()).endswith(".py") else (str(arguments.arguments[0].extract_value()) + ";\n")) + "interpreter._globals.variables.append(('" + str(arguments.arguments[1].extract_value()) + "', VariableType.Function, BuiltinFunction('" + str(arguments.arguments[1].extract_value()) + "', None, " + (str(arguments.arguments[2].extract_value()) if len(arguments.arguments) > 2 else str(arguments.arguments[1].extract_value())) + "))); interpreter._globals.apply_to_scope(arguments.interpreter.current_scope);") or None)



if str(arguments.arguments[0].extract_value()).endswith(".py"):
code = ("from " + str(arguments.arguments[0].extract_value()).replace(".py", "").replace("/", ".") + " import *;")
else:
code = str(arguments.arguments[0].extract_value()) + ";\n"
code += "interpreter._globals.variables.append(('" + str(arguments.arguments[1].extract_value()) + "', VariableType.Function, BuiltinFunction('" + str(arguments.arguments[1].extract_value()) + "', None, "
if len(arguments.arguments) > 2:
code += str(arguments.arguments[2].extract_value())
else:
code += str(arguments.arguments[1].extract_value())
code += "))); interpreter._globals.apply_to_scope(arguments.interpreter.current_scope);"

exec(code)

return BasicValue(None)
10 changes: 9 additions & 1 deletion interpreter/env/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,14 @@ def __init__(self):

('__intern_dictionary_len__', VariableType.Function, BuiltinFunction("__intern_dictionary_len__", None, builtin_dictionary_len)),
('__intern_dictionary_at__', VariableType.Function, BuiltinFunction("__intern_dictionary_at__", None, builtin_dictionary_at)),
('__intern_dictionary_atindex__', VariableType.Function, BuiltinFunction("__intern_dictionary_atindex__", None, builtin_dictionary_atindex)),
('__intern_dictionary_indexatkey__', VariableType.Function, BuiltinFunction("__intern_dictionary_indexatkey__", None, builtin_dictionary_indexatkey)),
('__intern_dictionary_append__', VariableType.Function, BuiltinFunction("__intern_dictionary_append__", None, builtin_dictionary_append)),
('__intern_dictionary_set__', VariableType.Function, BuiltinFunction("__intern_dictionary_set__", None, builtin_dictionary_set)),
('__intern_dictionary_clone__', VariableType.Function, BuiltinFunction("__intern_dictionary_clone__", None, builtin_dictionary_clone)),
('__intern_dictionary_keys__', VariableType.Function, BuiltinFunction("__intern_dictionary_keys__", None, builtin_dictionary_keys)),
('__intern_dictionary_values__', VariableType.Function, BuiltinFunction("__intern_dictionary_values__", None, builtin_dictionary_values)),
('__intern_dictionary_contains__', VariableType.Function, BuiltinFunction("__intern_dictionary_contains__", None, builtin_dictionary_contains)),

('__intern_console_input__', VariableType.Function, BuiltinFunction("__intern_console_input__", None, builtin_console_input)),
('__intern_file_read__', VariableType.Function, BuiltinFunction("__intern_file_read__", None, builtin_file_read)),
Expand Down Expand Up @@ -378,7 +383,10 @@ def __init__(self):

('__intern_macro_expand__', VariableType.Function, BuiltinFunction("__intern_macro_expand__", None, builtin_macro_expand)),

('__intern_import_python__', VariableType.Function, BuiltinFunction("__intern_import_python__", None, lambda arguments, self=self : exec((("from " + str(arguments.arguments[0].extract_value()).replace(".py", "").replace("/", ".") + " import *;") if str(arguments.arguments[0].extract_value()).endswith(".py") else (str(arguments.arguments[0].extract_value()) + ";\n")) + "self.variables.append(('" + str(arguments.arguments[1].extract_value()) + "', VariableType.Function, BuiltinFunction('" + str(arguments.arguments[1].extract_value()) + "', None, " + (str(arguments.arguments[2].extract_value()) if len(arguments.arguments) > 2 else str(arguments.arguments[1].extract_value())) + "))); self.apply_to_scope(arguments.interpreter.current_scope);") or BasicValue(None)))
('__intern_import_python__', VariableType.Function, BuiltinFunction("__intern_import_python__", None, builtin_import_python))
# ('__intern_import_python__', VariableType.Function, BuiltinFunction("__intern_import_python__", None, lambda arguments, self=self : exec((("from " + str(arguments.arguments[0].extract_value()).replace(".py", "").replace("/", ".") + " import *;") if str(arguments.arguments[0].extract_value()).endswith(".py") else (str(arguments.arguments[0].extract_value()) + ";\n")) + "self.variables.append(('" + str(arguments.arguments[1].extract_value()) + "', VariableType.Function, BuiltinFunction('" + str(arguments.arguments[1].extract_value()) + "', None, " + (str(arguments.arguments[2].extract_value()) if len(arguments.arguments) > 2 else str(arguments.arguments[1].extract_value())) + "))); self.apply_to_scope(arguments.interpreter.current_scope);") or BasicValue(None)))
# ('__intern_import_python__', VariableType.Function, BuiltinFunction("__intern_import_python__", None, lambda arguments, self=self : exec((("from " + str(arguments.arguments[0].extract_value()).replace(".py", "").replace("/", ".") + " import *;") if str(arguments.arguments[0].extract_value()).endswith(".py") else (str(arguments.arguments[0].extract_value()) + ";\n")) + "self.variables.append(('" + str(arguments.arguments[1].extract_value()) + "', VariableType.Function, BuiltinFunction('" + str(arguments.arguments[1].extract_value()) + "', None, " + (str(arguments.arguments[2].extract_value()) if len(arguments.arguments) > 2 else str(arguments.arguments[1].extract_value())) + "))); self.apply_to_scope(arguments.interpreter.current_scope);") or BasicValue(None)))
# ('__intern_import_python__', VariableType.Function, BuiltinFunction("__intern_import_python__", None, lambda arguments, self=self : exec((("from " + str(arguments.arguments[0].extract_value()).replace(".py", "").replace("/", ".") + " import *;") if str(arguments.arguments[0].extract_value()).endswith(".py") else (str(arguments.arguments[0].extract_value()) + ";\n")) + "self.variables.append(('" + str(arguments.arguments[1].extract_value()) + "', VariableType.Function, BuiltinFunction('" + str(arguments.arguments[1].extract_value()) + "', None, " + (str(arguments.arguments[2].extract_value()) if len(arguments.arguments) > 2 else str(arguments.arguments[1].extract_value())) + "))); self.apply_to_scope(arguments.interpreter.current_scope);") or BasicValue(None)))
]

def vartype_to_typeobject(self, vartype):
Expand Down
21 changes: 16 additions & 5 deletions interpreter/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ def __init__(self, source_location):
self.global_scope = Scope(None)
self._top_level_scope = None

Globals().apply_to_scope(self.global_scope)
# _globals is only used for pyimport
self._globals = Globals()
self._globals.apply_to_scope(self.global_scope)

@property
def current_scope(self):
Expand Down Expand Up @@ -983,12 +985,21 @@ def call_function_expression(self, node):
self.close_scope()

def visit_ArrayExpression(self, node):
members = []
if node.is_dictionary:
members = {}

for member_decl in node.members:
value = self.visit(member_decl)
for i in range(len(self.visit(node.members[0]).extract_value())):
key = self.visit(self.visit(node.members[0]).extract_value()[i])
value = self.visit(self.visit(node.members[1]).extract_value()[i])

members[key] = value
else:
members = []

for member_decl in node.members:
value = self.visit(member_decl)

members.append(value)
members.append(value)

return BasicValue(members)

Expand Down
9 changes: 8 additions & 1 deletion interpreter/scope.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,20 @@ def set_variable(self, name, value):
var.value_wrapper.assign_value(value)

def find_variable_info(self, name, limit=False):
# if name != "self":
# print(name)

if name in self.variables:
return self.variables[name]

if limit or self.parent is None:
return None

return self.parent.find_variable_info(name)
try:
return self.parent.find_variable_info(name)
except:
# TODO: Maybe throw an error.
return None

def find_variable_value(self, name, limit=False):
return self.find_variable_info(name, limit).value_wrapper
Expand Down
2 changes: 1 addition & 1 deletion interpreter/variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ class VariableType(Enum):
Auto = 'auto'
Int = 'int'
String = 'str'
Dict = 'dict'
Any = 'any'
Function = 'func'
Type = 'type'

Array = auto()
Dict = auto()
Object = auto() # Class, data structure, etc.

# class Variable(BasicValue):
Expand Down
Loading

0 comments on commit 8d66ebd

Please sign in to comment.