From 299dbf3ca78a47c188fa17c52dc223a94eaee9b9 Mon Sep 17 00:00:00 2001 From: Erik Stenman Date: Fri, 15 Feb 2019 09:28:04 +0100 Subject: [PATCH] Handle map instructions. --- include/aefa_opcodes.hrl | 1 + src/aefa_asm.erl | 2 ++ src/aefa_asm_scan.xrl | 5 +++ src/aefa_opcodes.erl | 74 ++++++++++++++++++++++++++-------------- test/asm_code/map.fate | 34 ++++++++++++++++++ 5 files changed, 90 insertions(+), 26 deletions(-) create mode 100644 test/asm_code/map.fate diff --git a/include/aefa_opcodes.hrl b/include/aefa_opcodes.hrl index a401c9f..e1f107c 100644 --- a/include/aefa_opcodes.hrl +++ b/include/aefa_opcodes.hrl @@ -101,6 +101,7 @@ -define('SHA256' , 16#66). -define('BLAKE2B' , 16#67). -define('RETURNR' , 16#68). +-define('MAP_LOOKUPD' , 16#69). -define('FUNCTION' , 16#fe). -define('EXTEND' , 16#ff). diff --git a/src/aefa_asm.erl b/src/aefa_asm.erl index 8ea5c9f..0a44267 100644 --- a/src/aefa_asm.erl +++ b/src/aefa_asm.erl @@ -388,6 +388,8 @@ to_bytecode([{stack,_line, N}|Rest], Address, Env, Code, Opts) -> to_bytecode(Rest, Address, Env, [{stack, N}|Code], Opts); to_bytecode([{int,_line, Int}|Rest], Address, Env, Code, Opts) -> to_bytecode(Rest, Address, Env, [{immediate, Int}|Code], Opts); +to_bytecode([{boolean,_line, Bool}|Rest], Address, Env, Code, Opts) -> + to_bytecode(Rest, Address, Env, [{immediate, Bool}|Code], Opts); to_bytecode([{hash,_line, Hash}|Rest], Address, Env, Code, Opts) -> to_bytecode(Rest, Address, Env, [{immediate, Hash}|Code], Opts); to_bytecode([{id,_line, ID}|Rest], Address, Env, Code, Opts) -> diff --git a/src/aefa_asm_scan.xrl b/src/aefa_asm_scan.xrl index 2a6ea2a..b61d240 100644 --- a/src/aefa_asm_scan.xrl +++ b/src/aefa_asm_scan.xrl @@ -25,6 +25,9 @@ var{INT} : {token, {var, TokenLine, parse_var(TokenChars)}}. a : {token, {stack, TokenLine, 0}}. a{INT} : {token, {stack, TokenLine, parse_acc(TokenChars)}}. +true : {token, {boolean, TokenLine, true}}. +false : {token, {boolean, TokenLine, false}}. + RETURN : {token, {mnemonic, TokenLine, 'RETURN'}}. RETURNR : {token, {mnemonic, TokenLine, 'RETURNR'}}. CALL : {token, {mnemonic, TokenLine, 'CALL'}}. @@ -70,8 +73,10 @@ ELEMENT : {token, {mnemonic, TokenLine, 'ELEMENT'}}. MAP_EMPTY : {token, {mnemonic, TokenLine, 'MAP_EMPTY'}}. MAP_LOOKUP : {token, {mnemonic, TokenLine, 'MAP_LOOKUP'}}. +MAP_LOOKUPD : {token, {mnemonic, TokenLine, 'MAP_LOOKUPD'}}. MAP_UPDATE : {token, {mnemonic, TokenLine, 'MAP_UPDATE'}}. MAP_MEMBER : {token, {mnemonic, TokenLine, 'MAP_MEMBER'}}. +MAP_DELETE : {token, {mnemonic, TokenLine, 'MAP_DELETE'}}. MAP_FROM_LIST : {token, {mnemonic, TokenLine, 'MAP_FROM_LIST'}}. NIL : {token, {mnemonic, TokenLine, 'NIL'}}. diff --git a/src/aefa_opcodes.erl b/src/aefa_opcodes.erl index 47730ee..20116e5 100644 --- a/src/aefa_opcodes.erl +++ b/src/aefa_opcodes.erl @@ -53,6 +53,14 @@ mnemonic(?NEQ) -> 'NEQ' ; mnemonic(?STORE) -> 'STORE' ; mnemonic(?TUPLE) -> 'TUPLE' ; mnemonic(?ELEMENT) -> 'ELEMENT' ; +mnemonic(?MAP_EMPTY) -> 'MAP_EMPTY' ; +mnemonic(?MAP_UPDATE) -> 'MAP_UPDATE' ; +mnemonic(?MAP_DELETE) -> 'MAP_DELETE' ; +mnemonic(?MAP_MEMBER) -> 'MAP_MEMBER' ; +mnemonic(?MAP_LOOKUP) -> 'MAP_LOOKUP' ; +mnemonic(?MAP_LOOKUPD) -> 'MAP_LOOKUPD'; +mnemonic(?MAP_FROM_LIST)->'MAP_FROM_LIST' ; + mnemonic(OP) -> {OP, nothandled}. m_to_op('NOP') -> ?NOP ; @@ -81,6 +89,13 @@ m_to_op('NEQ') -> ?NEQ ; m_to_op('STORE') -> ?STORE ; m_to_op('TUPLE') -> ?TUPLE ; m_to_op('ELEMENT') -> ?ELEMENT ; +m_to_op('MAP_EMPTY') -> ?MAP_EMPTY ; +m_to_op('MAP_UPDATE') -> ?MAP_UPDATE ; +m_to_op('MAP_DELETE') -> ?MAP_DELETE ; +m_to_op('MAP_MEMBER') -> ?MAP_MEMBER ; +m_to_op('MAP_LOOKUP') -> ?MAP_LOOKUP ; +m_to_op('MAP_LOOKUPD') -> ?MAP_LOOKUPD ; +m_to_op('MAP_FROM_LIST')->?MAP_FROM_LIST ; m_to_op('CALL') -> ?CALL ; m_to_op('CALL_T') -> ?CALL_T ; m_to_op('CALL_R') -> ?CALL_R ; @@ -90,35 +105,42 @@ args(?NOP) -> 0; args(?RETURN) -> 0; args(?INC) -> 0; -args(?RETURNR) -> 1; -args(?PUSH) -> 1; -args(?JUMP) -> 1; -args(?CALL) -> 1; -args(?CALL_T) -> 1; -args(?TUPLE) -> 1; +args(?RETURNR) -> 1; +args(?PUSH) -> 1; +args(?JUMP) -> 1; +args(?CALL) -> 1; +args(?CALL_T) -> 1; +args(?TUPLE) -> 1; +args(?MAP_EMPTY) -> 1; -args(?JUMPIF) -> 2; -args(?CALL_R) -> 2; -args(?CALL_TR) -> 2; -args(?NOT) -> 2; -args(?STORE) -> 2; +args(?JUMPIF) -> 2; +args(?CALL_R) -> 2; +args(?CALL_TR) -> 2; +args(?NOT) -> 2; +args(?STORE) -> 2; +args(?MAP_FROM_LIST) -> 2; -args(?ADD) -> 3; -args(?SUB) -> 3; -args(?MUL) -> 3; -args(?DIV) -> 3; -args(?MOD) -> 3; -args(?POW) -> 3; -args(?AND) -> 3; -args(?OR) -> 3; -args(?LT) -> 3; -args(?GT) -> 3; -args(?EGT) -> 3; -args(?ELT) -> 3; -args(?EQ) -> 3; -args(?NEQ) -> 3; +args(?ADD) -> 3; +args(?SUB) -> 3; +args(?MUL) -> 3; +args(?DIV) -> 3; +args(?MOD) -> 3; +args(?POW) -> 3; +args(?AND) -> 3; +args(?OR) -> 3; +args(?LT) -> 3; +args(?GT) -> 3; +args(?EGT) -> 3; +args(?ELT) -> 3; +args(?EQ) -> 3; +args(?NEQ) -> 3; +args(?MAP_MEMBER) -> 3; +args(?MAP_LOOKUP) -> 3; +args(?MAP_DELETE) -> 3; -args(?ELEMENT) -> 4; +args(?ELEMENT) -> 4; +args(?MAP_UPDATE) -> 4; +args(?MAP_LOOKUPD) -> 4; args(_) -> 0. %% TODO do not allow this diff --git a/test/asm_code/map.fate b/test/asm_code/map.fate new file mode 100644 index 0000000..beb1589 --- /dev/null +++ b/test/asm_code/map.fate @@ -0,0 +1,34 @@ +;; CONTRACT map +FUNCTION make_empty_map():{map, integer, boolean} + MAP_EMPTY a + RETURN + +FUNCTION map_update({map, integer, boolean}, integer, boolean):{map, integer, boolean} + MAP_UPDATE a arg0 arg1 arg2 + RETURN + +FUNCTION map_lookup({map, integer, boolean}, integer):boolean + MAP_LOOKUP a arg0 arg1 + RETURN + +FUNCTION map_lookup_default({map, integer, boolean}, integer): boolean + MAP_LOOKUPD a arg0 arg1 false + RETURN + +FUNCTION map_member({map, integer, boolean}, integer):boolean + MAP_MEMBER a arg0 arg1 + RETURN + +FUNCTION map_delete({map, integer, boolean}, integer):{map, integer, boolean} + MAP_DELETE a arg0 arg1 + RETURN + + +FUNCTION map_member({map, integer, boolean}, integer) : boolean + MAP_MEMBER a arg0 arg1 + RETURN + +FUNCTION map_from_list({list, {tuple, [integer, boolean]}}) : {map, integer, boolean} + MAP_FROM_LIST a arg0 + RETURN +