[Feature] Dictionary data structure user defined
- Lingua principale
- Rust
- Stelle
- 5.2k
- Fork
- 145
- Merge medio
- 5g 3h
- PR unite (30g)
- 7
Descrizione
Right now Amber doesn't support user-defined types. I think it would be a useful feature for a number of reasons. For example we can work with complex structures like JSON from the web or process structured data. I suggest implementing a dictionary data structure compatible with POSIX shells. Dictionary support should help supporting user-defined types as in other scripting languages. Although there is no dictionary in Bash it is possible to access data (dereference) knowing the corresponding variable's name. Thus a dictionary can be represented by a list of variable names. By dereferencing a variable from the list we will get the field's value in the dictionary. Below you can find the impementation of this idea
```bash
#!/bin/sh
stringContains() { case $1 in *$2* ) return 0;; *) return 1;; esac ;}
stringNotContains() { case $1 in *$2* ) return 1;; *) return 0;; esac ;}
lastObjTypeId=0
lastObjId=0
printError() {
>&2 echo $1
}
objNewId() {
lastObjId=$((lastObjId + 1)) # Each dictionary has it's own id
}
# Add a new field to the dictionary and set it's value
objSet() {
local objId=$1
local propId=$2
local value=$3
local place="place_o${objId}_${propId}"
eval "${place}=\$value"
local place="place_o${objId}__fields"
if [ ! -z ${!place} ] # add the new field to the fields list
then
local fieldsList=${!place}
if stringNotContains "$fieldsList" ":$propId:"; then
local newFields="${!place}$propId:"
eval "${place}=\$newFields"
fi
fi
}
# get value of the dictionarie's field
objGet() {
local objId=$1
local propId=$2
local place="place_o${objId}_${propId}"
result=${!place}
}
# store the information about object type
objNewType() {
local typeName=$1
local fieldsList=$2
objNewId
local typeObjId=${lastObjId}
objSet $typeObjId "_typeObjId" 0
objSet $typeObjId "name" $typeName
objSet $typeObjId "fields" ":_typeObjId:$fieldsList:"
local typeEntry="type_$typeName"
eval "${typeEntry}=$typeObjId"
}
place_o0__typeObjId="0"
place_o0_fields=":_typeObjId:fields:name:"
place_o0_name="TypeInfo"
type_TypeInfo="0"
# create new empty object
objNew() {
objNewId
local objId=${lastObjId}
objSet $objId "_fields" ":_fields:"
result=$objId
}
objNewTyped() {
local typeName=$1
local typeEntry="type_$typeName"
local typeId=${!typeEntry}
objNewId
local objId=${lastObjId}
objSet $objId "_typeObjId" $typeId
result=$objId
}
objDestroy() {
local objId=$1
local place="place_o${objId}__typeObjId"
local fieldsList=":"
if [ ! -z ${!place} ]
then
# obj is typed, iterate over fields from type info
objGet ${!place} "fields"
fieldsList=${result}
else
local place="place_o${objId}__fields"
if [ ! -z ${place} ]
then
fieldsList=${!place}
else
printError "Unknown kind of object"
exit 1
fi
fi
IFS=":"
for propId in $fieldsList; do
if [ ! -z $propId ]
then
local place="place_o${objId}_${propId}"
eval "unset ${place}"
fi
done
}
echo "-----------------"
objNewType "T" "x:y:z"
objNewTyped "T"
a=${result}
objNew
b=${result}
echo "a is $a"
echo "b is $b"
objSet $a "x" 1
objSet $a "y" 2
objSet $a "y" "d"
objSet $a "z" 3
objSet $b "x" "ff"
objSet $b "a" 13
objSet $b "b" 14
objSet $b "a" 18
objGet $a "x"
echo $result
objGet $a "y"
echo $result
objGet $a "z"
echo $result
objGet $b "x"
echo $result
objGet $b "a"
echo $result
objGet $b "b"
echo $result
declare -p | grep type_
declare -p | grep place
echo "-----------------"
objDestroy $a
objDestroy $b
declare -p | grep place
```
Using this approach we can support nested dictionaries as well. Now I want to add dictionary syntax support to Amber and AST generation. It will look like this
```Rust
// Definition
let dict = {
a: 10,
b: {
x: "Hello",
y: 20
},
c: 42
}
// Access
let result = dict.a + dict.b.y + dict.c
// Set new field value
dict.x = 5
```
What do you think? Are there any problems I missed?
Guida per i contributori
Nessuna guida per i contributori indicizzata per questo repository
Valutazione
Questa issue non è ancora stata valutata.