Syntaxe de l'Assembly
Opérations
; Définitions des types
- LOAD_CONST 0x01
- LOAD_VAR 0x02
- STORE_VAR 0x03
- BINARY_OP 0x04
- UNARY_OP 0x05
- COMPARE_OP 0x06
- JUMP_IF_TRUE 0x07
- JUMP_IF_FALSE 0x08
- JUMP 0x09
- JUMP_NEW_SCOPE 0x0A
- POP 0x0B
- DUP 0x0C
- CALL 0x0D
- RETURN 0x0E
- LOAD_PC 0x0F
- INDEX 0x10
- SAVE_AT 0x11
-
LOAD_CONST(index): Charge une valeur constante sur la pile. L'
index
pointe vers la position de la constante dans un pool de constantes. -
LOAD_VAR(name): Charge la valeur d'une variable sur la pile. Le
name
est l'identifiant de la variable. -
STORE_VAR(name): Stocke la valeur en haut de la pile dans la variable avec le
name
donné. -
BINARY_OP(operator): Effectue une opération binaire sur les deux valeurs supérieures de la pile. L'
operator
indique l'opération (addition, soustraction, multiplication, etc.). -
UNARY_OP(operator): Effectue une opération unaire sur la valeur supérieure de la pile. L'
operator
indique l'opération (négation, NOT bit à bit, etc.). -
COMPARE_OP(operator): Compare les deux valeurs supérieures de la pile en utilisant l'
operator
spécifié (égal, non égal, inférieur, supérieur, etc.). -
JUMP_IF_TRUE(target): Saute à l'instruction
target
spécifiée si la valeur supérieure de la pile est vraie. -
JUMP_IF_FALSE(target): Saute à l'instruction
target
spécifiée si la valeur supérieure de la pile est fausse. -
JUMP(target): Saut inconditionnel vers l'instruction
target
spécifiée. -
JUMP_NEW_SCOPE(target): Saut inconditionnel vers l'instruction
target
spécifiée et crée une nouvelle portée vide de variables. -
POP: Dépile la valeur supérieure de la pile.
-
DUP: Duplique la valeur supérieure de la pile.
-
CALL(func_name, num_args): Appelle une fonction avec le
func_name
etnum_args
spécifiés comme arguments. -
RETURN: Retourne de la fonction en cours.
-
LOAD_PC: Charge le compteur de programme sur la pile.
-
INDEX: Place dans la stack la valeur du string à l'index donné. L'index est le premier élément de la stack, la string est le deuxième.
-
SAVE_AT: Sauvegarde dans la string à l'index donné la valeur donnée. Le string est le premier élément de la stack, l'index le deuxième, la valeur le troisième.
Exemples
Exemple 1
fun main (int spain🇪🇸) : int
{
return 0;
}
Est converti en AST:
-- AST
FunAST "main" (AST [IntTypeAST,SymbolAST "spain🇪🇸"]) (FunTypeAST (AST [IntTypeAST])) (ReturnAST (AST [IntAST 0]))
-- AST (human readable)
FunAST main
| AST
| | IntTypeAST
| | SymbolAST "spain🇪🇸"
| FunTypeAST
| | AST
| | | IntTypeAST
| ReturnAST
| | AST
| | | IntAST 0
Qui est converti en bytecode:
32 FunEntryPoint "main" IntType
37 StoreVarBefore spain🇪🇸 IntType # sauvagarde de la variable spain🇪🇸
43 LoadConst 0 IntType
49 Return
50 Return # return deus fois si l'utilisateur ne fait pas de return depuis le main
Devient:
32 Jump 37 # saute dans la fonction main, les 32 premiers octets sont le header
37 StoreVar 0 IntType
43 LoadConst 0 IntType
49 Return
50 Return
Le bytecode final est:
# le magic number
122,105,122,105,
# Le header: "This is the comment section\0"
84,104,105,115,32,105,115,32,116,104,101,32,99,111,109,109,101,110,116,32,115,101,99,116,105,111,110,0,
9,37,0,0,0, # Jump 37
3,0,0,0,0,1, # StoreVar 0 IntType
1,0,0,0,0,1, # LoadConst 0 IntType
14, # Return
14 # Return
Exemple 2
fun add (int a, int b) : (int)
{
return a + b;
}
fun main () : int
{
int south_corea🇰🇷 = 7;
int north_corea🇰🇵 = 3;
int corea = add(south_corea🇰🇷, north_corea🇰🇵);
return corea;
}
Est converti en AST:
AST
| FunAST add
| | AST
| | | AST
| | | | IntTypeAST
| | | | SymbolAST a
| | | AST
| | | | IntTypeAST
| | | | SymbolAST b
| | FunTypeAST
| | | AST
| | | | AST
| | | | | IntTypeAST
| | ReturnAST
| | | PlusAST
| | | | AST
| | | | | SymbolAST a
| | | | AST
| | | | | SymbolAST b
| FunAST main
| | DeadLeafAST
| | FunTypeAST
| | | AST
| | | | IntTypeAST
| | AST
| | | AssignAST
| | | | AST
| | | | | IntTypeAST
| | | | | SymbolAST south_corea🇰🇷
| | | | AST
| | | | | IntAST 7
| | | AssignAST
| | | | AST
| | | | | IntTypeAST
| | | | | SymbolAST north_corea🇰🇵
| | | | AST
| | | | | IntAST 3
| | | AssignAST
| | | | AST
| | | | | IntTypeAST
| | | | | SymbolAST corea
| | | | AST
| | | | | SymbolAST add
| | | | | AST
| | | | | | AST
| | | | | | | SymbolAST south_corea🇰🇷
| | | | | | AST
| | | | | | | SymbolAST north_corea🇰🇵
| | | ReturnAST
| | | | AST
| | | | | SymbolAST corea
Qui est converti en bytecode:
32 Jump 65
# add
37 StoreVar 0 IntType
43 StoreVar 1 IntType
49 LoadVar 0 IntType
55 LoadVar 1 IntType
61 BinaryOp +
63 Return
64 Return
# main
65 LoadConst 7 IntType
71 StoreVar 0 IntType
77 LoadConst 3 IntType
83 StoreVar 1 IntType
89 LoadVar 0 IntType
95 LoadVar 1 IntType
101 LoadPC
102 JumpNewScope 37
107 StoreVar 2 IntType
113 LoadVar 2 IntType
119 Return
120 Return
Comme on peut le voir, les variables sont stockées sous forme d'id, et les fonctions aussi.
Devient:
# Le magic number
122,105,122,105,
# Le header: "This is the comment section\0"
84,104,105,115,32,105,115,32,116,104,101,32,99,111,109,109,101,110,116,32,115,101,99,116,105,111,110,0,
9,65,0,0,0, # Jump 65
3,0,0,0,0,1, # StoreVar 0 IntType
3,1,0,0,0,1, # StoreVar 1 IntType
2,0,0,0,0,1, # LoadVar 0 IntType
2,1,0,0,0,1, # LoadVar 1 IntType
4,43, # BinaryOp +
14, # Return
14, # Return
1,7,0,0,0,1, # LoadConst 7 IntType
3,0,0,0,0,1, # StoreVar 0 IntType
1,3,0,0,0,1, # LoadConst 3 IntType
3,1,0,0,0,1, # StoreVar 1 IntType
2,0,0,0,0,1, # LoadVar 0 IntType
2,1,0,0,0,1, # LoadVar 1 IntType
15, # LoadPC
10,37,0,0,0, # JumpNewScope 37
3,2,0,0,0,1, # StoreVar 2 IntType
2,2,0,0,0,1, # LoadVar 2 IntType
14, # Return
14 # Return
Comme on peut le voir, les instructions LoadConst
, LoadVar
et StoreVar
fonctionnent comme ceci:
First byte:
0x01 # LoadConst
0x02 # LoadVar
0x03 # StoreVar
4 octets suivants sont l id de la variable ou, la valeur de la constante
0x00, 0x00, 0x00, 0x00 # 0
1 octet suivant est le type de la variable
0x01 # IntType
0x02 # FloatType
0x03 # StringType
0x04 # BoolType
Les syscalls
print (int value | char value | float value | string value)
// Syscall Number: 1 : Ecrire dans le stdout
getline ()
// Syscall Number: 2 : Lire une ligne depuis le stdin
readFile (string path)
// Syscall Number: 3 : Lire un fichier
writeInFile (string path, string content)
// Syscall Number: 4 : Ecrire dans un fichier
appendInFile (string path, string content)
// Syscall Number: 5 : Ecrire à la fin d`un fichier
exit (int status)
// Syscall Number: 60 : Termine le processus et retourne le status de sortie au parent.
Exemple of syscall usage
fun main () : int
{
print("\tUser 1:\n");
print("Enter a name:\n");
string name = getline();
print("Enter an age:\n");
string age = getline();
print("Enter a car:\n");
string car = getline();
writeInFile("file.json", "[\n\t{\n\t\t\"name\": \"" + name + "\",\n\t\t\"age\": \"" + age + "\",\n\t\t\"car\": \"" + car + "\"\n\t}");
print("\tUser 2:\n");
print("Enter a name:\n");
string name = getline();
print("Enter an age:\n");
string age = getline();
print("Enter a car:\n");
string car = getline();
appendInFile("file.json", ",\n\t{\n\t\t\"name\": \"" + name + "\",\n\t\t\"age\": \"" + age + "\",\n\t\t\"car\": \"" + car + "\"\n\t}\n]\n");
return 0;
}