From 8c95b488530800bebd1b0c5b42a4364558b8c0a2 Mon Sep 17 00:00:00 2001 From: Ash Ranjan Date: Wed, 7 Jul 2021 22:11:56 -0700 Subject: [PATCH 1/2] add value access --- python/operation_types.py | 42 +++++++++++++++++++- python/run.n | 80 +-------------------------------------- python/scope.py | 13 +++++++ python/syntax.lark | 11 +++++- 4 files changed, 64 insertions(+), 82 deletions(-) diff --git a/python/operation_types.py b/python/operation_types.py index ccf8f59b..7a187d5d 100644 --- a/python/operation_types.py +++ b/python/operation_types.py @@ -1,5 +1,5 @@ from type import NTypeVars, NGenericType -from native_types import n_list_type, list_generic, n_map_type +from native_types import n_list_type, list_generic, n_map_type, n_maybe_type # Might move these into Scope one day because these might be scoped due to # implementations of traits. @@ -9,6 +9,10 @@ in_map_generic = NGenericType("k") in_value_generic = NGenericType("v") +access_list_generic = NGenericType("t") +access_map_generic = NGenericType("k") +access_value_generic = NGenericType("v") + binary_operation_types = { "OR": [("bool", "bool", "bool"), ("int", "int", "int")], "AND": [("bool", "bool", "bool"), ("int", "int", "int")], @@ -40,6 +44,42 @@ # Exponents are weird because negative powers result in non-integers. # TODO: Make int ^ int an int; negative powers should result in 0. "EXPONENT": [("int", "int", "float"), ("float", "float", "float")], + "VALUEACCESS": [ + ( + n_list_type.with_typevars([access_list_generic]), + "int", + n_maybe_type.with_typevars([access_list_generic]), + ), ( + n_map_type.with_typevars([ + access_map_generic, + access_value_generic, + ]), + access_map_generic, + n_maybe_type.with_typevars([access_value_generic]), + ), + ( + "str", + "int", + "char", + ), + ( + n_maybe_type.with_typevars([n_list_type.with_typevars([access_list_generic])]), + "int", + n_maybe_type.with_typevars([access_list_generic]), + ), ( + n_maybe_type.with_typevars([n_map_type.with_typevars([ + access_map_generic, + access_value_generic, + ])]), + access_map_generic, + n_maybe_type.with_typevars([access_value_generic]), + ), + ( + n_maybe_type.with_typevars(["str"]), + "int", + n_maybe_type.with_typevars(["char"]), + ), + ] } unary_operation_types = { "SUBTRACT": [("int", "int"), ("float", "float")], diff --git a/python/run.n b/python/run.n index 2587a5fa..9629a86d 100644 --- a/python/run.n +++ b/python/run.n @@ -1,79 +1 @@ -import times -import FileIO -import request -import json -import websocket - -let textToBytes = [text:str] -> list[int] { - let b = [] - for (i in range(0, len(text), 1)) { - if let = text |> charAt(i) { - var b = b |> append(charCode(c)) - } - var b = b |> append(0) - } - return b -} - -let thing = [] -> cmd[()] { - let imageData = FileIO.readBytes("C:\\Users\\Ashvin Ranjan\\Downloads\\IMG_1499.jpg")! |> default([1]) - let image = "" - for (byte in imageData) { - var image = image + intCode(byte) - } - print(times.getTime()!) - let _ = FileIO.appendBytes("test.txt", [26, 26])! - print(FileIO.readBytes("test.txt")!) - print(request.delete("https://github.com", mapFrom([("", "")]))!) - let _ = request.createServer(3000, - [path:str requestType:str data:json.value] -> cmd[{ responseCode:int; data:list[int]; headers:map[str, str]; mimetype:str }] { - if (path == "" && requestType == "GET") { - return { - responseCode: 200 - data: textToBytes("oops"); - headers: mapFrom([ - ("Access-Control-Allow-Origin", "*"), - ("Content-Type", "text/html"), - ]) - mimetype: "text/html" - } - } - return { - responseCode: 404 - data: textToBytes("oops"); - headers: mapFrom([ - ("Access-Control-Allow-Origin", "*"), - ("Content-Type", "text/plain"), - ]) - mimetype: "text/plain" - } - } - )! -} - - -print(getType(thing)) -print(getType(imp "./runner.n")) - -let thing2 = [] -> cmd[()] { - print("opening the websocket!") - let _ = websocket.createServer( - { - onConnect: [user:websocket.user path:str] -> cmd[bool] { - print(user) - let _ = user.send("hello")! - return false - } - onMessage: [user:websocket.user message:str] -> cmd[bool] { - print(message) - let _ = user.send(message)! - // user.disconnect() - return false - } - onDisconnect: [user:websocket.user exitData:maybe[{ code: int; reason:str }]] -> cmd[bool] { return false } - }, - 3000 - )! -} - -let pub test = thing2() +print(["12", "1", "2"][1][1]) \ No newline at end of file diff --git a/python/scope.py b/python/scope.py index dc400a4f..9960f505 100644 --- a/python/scope.py +++ b/python/scope.py @@ -994,6 +994,19 @@ async def eval_expr(self, expr): raise SyntaxError( "Unexpected operation for unary_expression: %s" % operation ) + elif expr.data == "value_access": + left, _, right = expr.children + eval_left = await self.eval_expr(left) + if isinstance(eval_left, EnumValue) and eval_left == none: + return none + try: + if isinstance(eval_left, EnumValue): + eval_left = eval_left.values[0] + return yes(eval_left[await self.eval_expr(right)]) + except Exception as err: + if isinstance(err, IndexError) or isinstance(err, KeyError): + return none + raise err elif expr.data == "char": val = expr.children[0] if isinstance(val, lark.Tree): diff --git a/python/syntax.lark b/python/syntax.lark index 970ae7cb..46da188e 100644 --- a/python/syntax.lark +++ b/python/syntax.lark @@ -165,12 +165,18 @@ func_type: generic_declaration? (func_inner_type "->")+ not_func_type // Exponentiation right to left associative ?exponent_expression: unary_expression [EXPONENT exponent_expression] ?unary_expression: await_expression - | NOT unary_expression + | NOT | SUBTRACT unary_expression + ?await_expression: record_access | await_expression AWAIT -?record_access: value + +?record_access: value_access | await_expression "." CNAME + +?value_access: value + | await_expression VALUEACCESS expression "]" + value: NUMBER | BOOLEAN | STRING @@ -227,6 +233,7 @@ AWAIT: "!" PUBLIC: "pub" UNIT: "()" EMPTY: "_" +VALUEACCESS: "[" STRING: /"(?:[^\r\n\\\"]|\\(?:[nrtv0fb\"\\]|u\{[0-9a-fA-F]+\}|\{.\}))*"/ %import common.SIGNED_NUMBER -> NUMBER From 1d1ec91266ff18e0ac11f4a6c0cc30d9e7180e93 Mon Sep 17 00:00:00 2001 From: Ash Ranjan Date: Wed, 7 Jul 2021 22:17:58 -0700 Subject: [PATCH 2/2] update for the new tests --- python/operation_types.py | 2 +- tests/assertions/value-access.n | 2 +- tests/syntax/value-access.n | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/python/operation_types.py b/python/operation_types.py index 7a187d5d..fb9b97db 100644 --- a/python/operation_types.py +++ b/python/operation_types.py @@ -60,7 +60,7 @@ ( "str", "int", - "char", + n_maybe_type.with_typevars(["char"]), ), ( n_maybe_type.with_typevars([n_list_type.with_typevars([access_list_generic])]), diff --git a/tests/assertions/value-access.n b/tests/assertions/value-access.n index 26c50b87..4125d3ba 100644 --- a/tests/assertions/value-access.n +++ b/tests/assertions/value-access.n @@ -28,7 +28,7 @@ let nestedMap = mapFrom([ ), ]) assert type nestedMap["english"]["apple"] : maybe[str] -assert value nestedMap["english"]["apple"] == "orangen't" +assert value nestedMap["english"]["apple"] == yes("orangen't") // Strings diff --git a/tests/syntax/value-access.n b/tests/syntax/value-access.n index ca36d195..4f0a7db2 100644 --- a/tests/syntax/value-access.n +++ b/tests/syntax/value-access.n @@ -20,7 +20,7 @@ let a = -( )! )[(g |> h)] )() - )([i | j)] + )([i | j]) )[([])] ) let b = (