From 4b139019c90253631b924c70fece10785fcbabad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Reuh=20Fildadut?= Date: Sun, 25 Apr 2021 19:10:37 +0200 Subject: [PATCH] Add list assignment operators --- README.md | 2 + ideas.txt | 2 - stdlib/functions.lua | 55 +++++++++++++++++++++++ test/tests/list assignement.ans | 20 +++++++++ test/tests/list assignement.lua | 78 +++++++++++++++++++++++++++++++++ test/tests/named varag.ans | 10 +++++ test/tests/named varag.lua | 14 ++++++ 7 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 test/tests/list assignement.ans create mode 100644 test/tests/list assignement.lua create mode 100644 test/tests/named varag.ans create mode 100644 test/tests/named varag.lua diff --git a/README.md b/README.md index 8cee72f..35dc94f 100644 --- a/README.md +++ b/README.md @@ -685,6 +685,8 @@ Built-in operators: `a := b`: evaluate b, assign its value to identifier `a`. Returns the new value. +`a(index) := b`: evaluate b, assign its value to element of specific index in list `a`. Element is searched using the same method as list index operator `a(b)`; if indexing using a string and an associated pair doesn't exist, add a new one at the end of the list. Returns the new value. + `a += b`: evaluate b, assign its the current value of a `+` the value of b to a. Returns the new value. `-=`, `*=`, `/=`, `//=`, `%=`, `^=`: same with other arithmetic operators. diff --git a/ideas.txt b/ideas.txt index a931fd8..352d355 100644 --- a/ideas.txt +++ b/ideas.txt @@ -5,8 +5,6 @@ Probably won't be able to remove them completely (since lists can have mixed typ Ideally, we'd avoid runtime type checking. TODO: test reacheability of script paths -TODO: functions with default value for arguments / named parameters. Use = as name-value delimiter. -TODO: allow passing varargs as is to another function call Symbols still available: ` diff --git a/stdlib/functions.lua b/stdlib/functions.lua index c270cc9..eee173c 100644 --- a/stdlib/functions.lua +++ b/stdlib/functions.lua @@ -29,6 +29,9 @@ local function compare(a, b) end end +local numeric_index +local string_index + local functions functions = { -- discard left @@ -40,6 +43,55 @@ functions = { }, -- assignement [":="] = { + -- assign to numeric index + { + arity = 2, mode = "custom", + check = function(state, args) + local left = args[1] + return left.type == "function" and left.variant == numeric_index and left.argument.expression.left.type == "variable" + end, + value = function(state, exp) + local arg = exp.argument.expression + local name = arg.left.argument.expression.left.name + local index, indexe = eval(state, arg.left.argument.expression.right) + if not index then return index, indexe end + local right, righte = eval(state, arg.right) + if not right then return right, righte end + state.variables[name].value[index.value] = right + return right + end + }, + -- assign to string index + { + arity = 2, mode = "custom", + check = function(state, args) + local left = args[1] + return left.type == "function" and left.variant == string_index and left.argument.expression.left.type == "variable" + end, + value = function(state, exp) + local arg = exp.argument.expression + local name = arg.left.argument.expression.left.name + local index, indexe = eval(state, arg.left.argument.expression.right) + if not index then return index, indexe end + local right, righte = eval(state, arg.right) + if not right then return right, righte end + -- update index + local list = state.variables[name].value + for _,v in ipairs(list) do + if v.type == "pair" and compare(v.value[1], index) then + v.value[2] = right + return right + end + end + -- new index + table.insert(list, { + type = "pair", + value = { index, right } + }) + return right + end + }, + -- assign to direct variable { arity = 2, mode = "custom", check = function(state, args) @@ -392,6 +444,9 @@ functions = { end } +numeric_index = functions["("][1] +string_index = functions["("][2] + package.loaded[...] = functions truthy = require((...):gsub("stdlib%.functions$", "interpreter.common")).truthy eval = require((...):gsub("stdlib%.functions$", "interpreter.expression")) diff --git a/test/tests/list assignement.ans b/test/tests/list assignement.ans new file mode 100644 index 0000000..83a202d --- /dev/null +++ b/test/tests/list assignement.ans @@ -0,0 +1,20 @@ +:[1,2] x + +{x} + +{x(1) := 3} + +{x} + +{x("foo") := "a"} + +{x} + +{x("bar") := "b"} + +{x} + +{x("foo") := "c"} + +{x} + diff --git a/test/tests/list assignement.lua b/test/tests/list assignement.lua new file mode 100644 index 0000000..04cdaa5 --- /dev/null +++ b/test/tests/list assignement.lua @@ -0,0 +1,78 @@ +local _={} +_[37]={} +_[36]={} +_[35]={} +_[34]={} +_[33]={} +_[32]={} +_[31]={} +_[30]={} +_[29]={} +_[28]={data="[3, 2, foo:c, bar:b]",tags=_[37]} +_[27]={data="c",tags=_[36]} +_[26]={data="[3, 2, foo:a, bar:b]",tags=_[35]} +_[25]={data="b",tags=_[34]} +_[24]={data="[3, 2, foo:a]",tags=_[33]} +_[23]={data="a",tags=_[32]} +_[22]={data="[3, 2]",tags=_[31]} +_[21]={data="3",tags=_[30]} +_[20]={data="[1, 2]",tags=_[29]} +_[19]={_[28]} +_[18]={_[27]} +_[17]={_[26]} +_[16]={_[25]} +_[15]={_[24]} +_[14]={_[23]} +_[13]={_[22]} +_[12]={_[21]} +_[11]={_[20]} +_[10]={"return"} +_[9]={"text",_[19]} +_[8]={"text",_[18]} +_[7]={"text",_[17]} +_[6]={"text",_[16]} +_[5]={"text",_[15]} +_[4]={"text",_[14]} +_[3]={"text",_[13]} +_[2]={"text",_[12]} +_[1]={"text",_[11]} +return {_[1],_[2],_[3],_[4],_[5],_[6],_[7],_[8],_[9],_[10]} +--[[ +{ "text", { { + data = "[1, 2]", + tags = {} + } } } +{ "text", { { + data = "3", + tags = {} + } } } +{ "text", { { + data = "[3, 2]", + tags = {} + } } } +{ "text", { { + data = "a", + tags = {} + } } } +{ "text", { { + data = "[3, 2, foo:a]", + tags = {} + } } } +{ "text", { { + data = "b", + tags = {} + } } } +{ "text", { { + data = "[3, 2, foo:a, bar:b]", + tags = {} + } } } +{ "text", { { + data = "c", + tags = {} + } } } +{ "text", { { + data = "[3, 2, foo:c, bar:b]", + tags = {} + } } } +{ "return" } +]]-- \ No newline at end of file diff --git a/test/tests/named varag.ans b/test/tests/named varag.ans new file mode 100644 index 0000000..51f6a8a --- /dev/null +++ b/test/tests/named varag.ans @@ -0,0 +1,10 @@ +$ f(l...) + ~ l.len + :0 a + ~ a := l(1) + ~ l.remove(1) + @a + f(l=l) + ~~ + @0 + +{f(1,2,3,4,5)} diff --git a/test/tests/named varag.lua b/test/tests/named varag.lua new file mode 100644 index 0000000..ace1c98 --- /dev/null +++ b/test/tests/named varag.lua @@ -0,0 +1,14 @@ +local _={} +_[5]={} +_[4]={tags=_[5],data="15"} +_[3]={_[4]} +_[2]={"return"} +_[1]={"text",_[3]} +return {_[1],_[2]} +--[[ +{ "text", { { + data = "15", + tags = {} + } } } +{ "return" } +]]-- \ No newline at end of file