amber-lang / amber-lang/amber

[Feature] Dictionary data structure user defined

Aperta
#683 5 commenti 1 reazione 0 assegnatari Vedi su GitHub
syntax
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.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.