[script] Add support for unary operations (!/+/-/++/--)

Allows execution of unary operations: Pre/postfix inc/decrement, logical
negation and unary plus/minus.

The writebacks of increment/decrements happen during the execution of the
expression, unlike C where they are executed after the line if executed. This
is the case simply because it is simpler to execute this way.
This commit is contained in:
Charlie Brej 2009-06-22 16:48:46 +01:00 committed by Ray Strode
parent efb543e294
commit bccf288229
4 changed files with 178 additions and 14 deletions

View file

@ -9,12 +9,12 @@
#include <stdbool.h>
#include <string.h>
#include <stdbool.h>
#include <math.h>
#include "script.h"
#include "script-execute.h"
#include "script-object.h"
static script_obj* script_evaluate (script_state* state, script_exp* exp);
static script_obj* script_evaluate_plus (script_state* state, script_exp* exp)
@ -392,7 +392,6 @@ static script_obj* script_evaluate_assign (script_state* state, script_exp* exp)
script_obj* script_obj_a = script_evaluate (state, exp->data.dual.sub_a);
script_obj* script_obj_b = script_evaluate (state, exp->data.dual.sub_b);
script_obj_deref (&script_obj_b);
script_obj_reset (script_obj_a);
script_obj_assign (script_obj_a, script_obj_b);
script_obj_unref(script_obj_b);
@ -515,6 +514,10 @@ static script_obj* script_evaluate_cmp (script_state* state, script_exp* exp)
}
break;
}
case SCRIPT_OBJ_TYPE_REF:
{
assert(0);
}
}
if(valset){
if (val < 0) {lt = 1; ne = 1;}
@ -565,6 +568,62 @@ static script_obj* script_evaluate_logic (script_state* state, script_exp* exp)
return obj;
}
static script_obj* script_evaluate_unary (script_state* state, script_exp* exp)
{
script_obj* obj = script_evaluate (state, exp->data.sub);
script_obj* new_obj;
script_obj_deref (&obj);
if (exp->type == SCRIPT_EXP_TYPE_NOT){
int reply = !script_obj_as_bool(obj);
script_obj_unref (obj);
return script_obj_new_int (reply);
}
if (exp->type == SCRIPT_EXP_TYPE_POS){ // FIXME what should happen on non number operands?
return obj; // Does nothing, maybe just remove at parse stage
}
if (exp->type == SCRIPT_EXP_TYPE_NEG){
if (obj->type == SCRIPT_OBJ_TYPE_INT){
new_obj = script_obj_new_int (-obj->data.integer);
}
else if (obj->type == SCRIPT_OBJ_TYPE_FLOAT){
new_obj = script_obj_new_float (-obj->data.floatpoint);
}
else new_obj = script_obj_new_null ();
script_obj_unref (obj);
return new_obj;
}
int change_pre = 0;
int change_post;
if (exp->type == SCRIPT_EXP_TYPE_PRE_INC || SCRIPT_EXP_TYPE_POST_INC)
change_post = 1;
else
change_post = -1;
if (exp->type == SCRIPT_EXP_TYPE_PRE_INC)
change_pre = 1;
else if (exp->type == SCRIPT_EXP_TYPE_PRE_DEC)
change_pre = -1;
if (obj->type == SCRIPT_OBJ_TYPE_INT){
new_obj = script_obj_new_int (obj->data.integer + change_pre);
obj->data.integer += change_post;
}
else if (obj->type == SCRIPT_OBJ_TYPE_FLOAT){
new_obj = script_obj_new_float (obj->data.floatpoint + change_pre);
obj->data.floatpoint += change_post;
}
else {
new_obj = script_obj_new_null (); // If performeing something like a=hash++; a and hash become NULL
script_obj_reset (obj);
}
script_obj_unref (obj);
return new_obj;
}
static script_obj* script_evaluate_func (script_state* state, script_exp* exp)
{
script_state localstate;
@ -664,6 +723,16 @@ static script_obj* script_evaluate (script_state* state, script_exp* exp)
{
return script_evaluate_logic (state, exp);
}
case SCRIPT_EXP_TYPE_NOT:
case SCRIPT_EXP_TYPE_POS:
case SCRIPT_EXP_TYPE_NEG:
case SCRIPT_EXP_TYPE_PRE_INC:
case SCRIPT_EXP_TYPE_PRE_DEC:
case SCRIPT_EXP_TYPE_POST_INC:
case SCRIPT_EXP_TYPE_POST_DEC:
{
return script_evaluate_unary (state, exp);
}
case SCRIPT_EXP_TYPE_TERM_INT:
{
return script_obj_new_int (exp->data.integer);

View file

@ -21,14 +21,16 @@
/* done todo
int var (exp) tm = ! ++ --
f() f[] f.a pi =
int var (exp) tm =
f() f[] f.a pi =
pre: ! ++ -- + - pr =
post: ++ -- po =
* / % md =
+ - pm =
< <= > >= gt =
== != eq =
&& an
|| or
&& an =
|| or =
= as = += -= *= %=
*/
@ -166,11 +168,88 @@ static script_exp* script_parse_exp_pi (ply_scan_t* scan)
}
static script_exp* script_parse_exp_pr (ply_scan_t* scan)
{
script_exp_type type;
ply_scan_token_t* curtoken = ply_scan_get_current_token(scan);
ply_scan_token_t* peektoken = ply_scan_peek_next_token(scan);
if (curtoken->type == PLY_SCAN_TOKEN_TYPE_SYMBOL){
if (curtoken->data.symbol == '+'){
if (peektoken->type == PLY_SCAN_TOKEN_TYPE_SYMBOL && peektoken->data.symbol == '+'){
ply_scan_get_next_token(scan);
ply_scan_get_next_token(scan);
type = SCRIPT_EXP_TYPE_PRE_INC;
}
else {
ply_scan_get_next_token(scan);
type = SCRIPT_EXP_TYPE_POS;
}
}
else if (curtoken->data.symbol == '-'){
if (peektoken->type == PLY_SCAN_TOKEN_TYPE_SYMBOL && peektoken->data.symbol == '-'){
ply_scan_get_next_token(scan);
ply_scan_get_next_token(scan);
type = SCRIPT_EXP_TYPE_PRE_DEC;
}
else {
ply_scan_get_next_token(scan);
type = SCRIPT_EXP_TYPE_NEG;
}
}
else if (curtoken->data.symbol == '!'){
ply_scan_get_next_token(scan);
type = SCRIPT_EXP_TYPE_NOT;
}
else {
return script_parse_exp_pi (scan);
}
script_exp* exp = malloc(sizeof(script_exp));
exp->type = type;
exp->data.sub = script_parse_exp_pr (scan);
return exp;
}
return script_parse_exp_pi (scan);
}
static script_exp* script_parse_exp_po (ply_scan_t* scan)
{
script_exp* exp = script_parse_exp_pr (scan);
while (true){
ply_scan_token_t* curtoken = ply_scan_get_current_token(scan);
ply_scan_token_t* peektoken = ply_scan_peek_next_token(scan);
if (curtoken->type != PLY_SCAN_TOKEN_TYPE_SYMBOL) break;
if (peektoken->type != PLY_SCAN_TOKEN_TYPE_SYMBOL) break;
if (curtoken->data.symbol == '+' && peektoken->data.symbol == '+') {
ply_scan_get_next_token(scan);
ply_scan_get_next_token(scan);
script_exp* new_exp = malloc(sizeof(script_exp));
new_exp->type = SCRIPT_EXP_TYPE_POST_INC;
new_exp->data.sub = exp;
exp = new_exp;
}
else if (curtoken->data.symbol == '-' && peektoken->data.symbol == '-') {
ply_scan_get_next_token(scan);
ply_scan_get_next_token(scan);
script_exp* new_exp = malloc(sizeof(script_exp));
new_exp->type = SCRIPT_EXP_TYPE_POST_DEC;
new_exp->data.sub = exp;
exp = new_exp;
}
else break;
}
return exp;
}
static script_exp* script_parse_exp_md (ply_scan_t* scan)
{
script_exp* sub_a = script_parse_exp_pi (scan);
script_exp* sub_a = script_parse_exp_po (scan);
if (!sub_a) return NULL;
ply_scan_token_t* curtoken = ply_scan_get_current_token(scan);
while (curtoken->type == PLY_SCAN_TOKEN_TYPE_SYMBOL &&
@ -183,7 +262,7 @@ static script_exp* script_parse_exp_md (ply_scan_t* scan)
else exp->type = SCRIPT_EXP_TYPE_MOD;
exp->data.dual.sub_a = sub_a;
ply_scan_get_next_token(scan);
exp->data.dual.sub_b = script_parse_exp_pi (scan);
exp->data.dual.sub_b = script_parse_exp_po (scan);
assert(exp->data.dual.sub_b); //FIXME syntax error
sub_a = exp;
curtoken = ply_scan_get_current_token(scan);
@ -576,6 +655,15 @@ static void script_parse_exp_free (script_exp* exp)
script_parse_exp_free (exp->data.dual.sub_a);
script_parse_exp_free (exp->data.dual.sub_b);
break;
case SCRIPT_EXP_TYPE_NOT:
case SCRIPT_EXP_TYPE_POS:
case SCRIPT_EXP_TYPE_NEG:
case SCRIPT_EXP_TYPE_PRE_INC:
case SCRIPT_EXP_TYPE_PRE_DEC:
case SCRIPT_EXP_TYPE_POST_INC:
case SCRIPT_EXP_TYPE_POST_DEC:
script_parse_exp_free (exp->data.sub);
break;
case SCRIPT_EXP_TYPE_TERM_INT:
case SCRIPT_EXP_TYPE_TERM_FLOAT:
case SCRIPT_EXP_TYPE_TERM_NULL:

View file

@ -120,6 +120,13 @@ typedef enum
SCRIPT_EXP_TYPE_NE,
SCRIPT_EXP_TYPE_AND,
SCRIPT_EXP_TYPE_OR,
SCRIPT_EXP_TYPE_NOT,
SCRIPT_EXP_TYPE_POS,
SCRIPT_EXP_TYPE_NEG,
SCRIPT_EXP_TYPE_PRE_INC,
SCRIPT_EXP_TYPE_PRE_DEC,
SCRIPT_EXP_TYPE_POST_INC,
SCRIPT_EXP_TYPE_POST_DEC,
SCRIPT_EXP_TYPE_HASH,
SCRIPT_EXP_TYPE_FUNCTION,
SCRIPT_EXP_TYPE_ASSIGN,

View file

@ -16,13 +16,13 @@ fun update_logo_sprite (sprite){
image_height = ImageGetHeight(sprite.image);
if (sprite.x < 0)
sprite.xd = global.random % 5 + 1;
sprite.xd = +(global.random % 5 + 1)/0.5;
if (sprite.y < 0)
sprite.yd = global.random % 5 + 1;
sprite.yd = +(global.random % 5 + 1)/0.5;
if ((sprite.x + image_width) > 800)
sprite.xd = 0 - (global.random % 5 + 1);
sprite.xd = -((global.random % 5 + 1)/0.5);
if ((sprite.y + image_height) > 600)
sprite.yd = 0 - (global.random % 5 + 1);
sprite.yd = -((global.random % 5 + 1)/0.5);
global.random = (1 + global.random * 7) % 101;
@ -35,9 +35,9 @@ fun update_logo_sprite (sprite){
fun refresh (){
index = 0;
while (index<30){
while (!(index>=30)){
update_logo_sprite (sprites[index]);
index = index + 1;
index++;
}
return;
}