Skip to content
Permalink
Browse files

Initial implementation of EVERY

  • Loading branch information
burnsauce committed Oct 2, 2017
1 parent 70c012c commit 8e9c3b78fec17a6bff051e76fffc727377273a58
Showing with 106 additions and 2 deletions.
  1. +23 −0 docs/ops/controlflow.toml
  2. +1 −0 module/config.mk
  3. +27 −0 src/every.c
  4. +15 −0 src/every.h
  5. +1 −0 src/match_token.rl
  6. +14 −0 src/ops/controlflow.c
  7. +1 −0 src/ops/controlflow.h
  8. +1 −1 src/ops/op.c
  9. +1 −0 src/ops/op_enum.h
  10. +13 −0 src/state.c
  11. +6 −0 src/state.h
  12. +2 −0 src/teletype.c
  13. +1 −1 tests/Makefile
@@ -81,6 +81,29 @@ W LT A 100: A * A A
A will be 256.
"""

[EVERY]
prototype = "EVERY x: ..."
short = "run the command every `x` times the command is called"
description = """
Runs the command every `x` times the line is executed. This is tracked on a per-line basis, so each script can have 6 different "dividers".
Here is a 1-script clock divider:
```
EVERY 2: TR.P 1
EVERY 4: TR.P 2
EVERY 8: TR.P 3
EVERY 16: TR.P 4
```
The numbers do _not_ need to be evenly divisible by each other, so there is no problem with:
```
EVERY 2: TR.P 1
EVERY 3: TR.P 2
```
"""

[PROB]
prototype = "PROB x: ..."
short = "potentially execute command with probability `x` (0-100)"
@@ -73,6 +73,7 @@ CSRCS = \
../module/preset_w_mode.c \
../module/usb_disk_mode.c \
../src/command.c \
../src/every.c \
../src/helpers.c \
../src/match_token.c \
../src/scanner.c \
@@ -0,0 +1,27 @@
#include <stdbool.h>
#include <stdint.h>
#include "every.h"

void every_tick(every_count_t *e) {
(e->count)++;
e->count %= e->mod;
}

bool every_is_now(every_count_t *e) {
return e->count == 0;
}

void every_set_count(every_count_t *e, int16_t count) {
if (count < 0)
count = 0;
e->count = count;
}

void every_set_mod(every_count_t *e, int16_t mod) {
if (mod < 0)
mod = -mod;
else if (mod == 0)
mod = 1; // lazy initialization
e->mod = mod;
e->count %= e->mod;
}
@@ -0,0 +1,15 @@
#ifndef _EVERY_H
#define _EVERY_H

typedef struct {
int16_t count;
int16_t mod;
} every_count_t;


void every_tick(every_count_t*);
bool every_is_now(every_count_t*);
void every_set_count(every_count_t*, int16_t);
void every_set_mod(every_count_t*, int16_t);

#endif
@@ -419,6 +419,7 @@
"ELSE" => { MATCH_MOD(E_MOD_ELSE); };
"L" => { MATCH_MOD(E_MOD_L); };
"W" => { MATCH_MOD(E_MOD_W); };
"EVERY" => { MATCH_MOD(E_MOD_EVERY); };

# delay
"PROB" => { MATCH_MOD(E_MOD_PROB); };
@@ -22,6 +22,8 @@ static void mod_L_func(scene_state_t *ss, exec_state_t *es, command_state_t *cs,
const tele_command_t *post_command);
static void mod_W_func(scene_state_t *ss, exec_state_t *es, command_state_t *cs,
const tele_command_t *post_command);
static void mod_EVERY_func(scene_state_t *ss, exec_state_t *es, command_state_t *cs,
const tele_command_t *post_command);

static void op_SCENE_get(const void *data, scene_state_t *ss, exec_state_t *es,
command_state_t *cs);
@@ -43,6 +45,7 @@ const tele_mod_t mod_ELIF = MAKE_MOD(ELIF, mod_ELIF_func, 1);
const tele_mod_t mod_ELSE = MAKE_MOD(ELSE, mod_ELSE_func, 0);
const tele_mod_t mod_L = MAKE_MOD(L, mod_L_func, 2);
const tele_mod_t mod_W = MAKE_MOD(W, mod_W_func, 1);
const tele_mod_t mod_EVERY = MAKE_MOD(EVERY, mod_EVERY_func, 1);

const tele_op_t op_SCRIPT =
MAKE_GET_SET_OP(SCRIPT, op_SCRIPT_get, op_SCRIPT_set, 0, true);
@@ -144,6 +147,17 @@ static void mod_W_func(scene_state_t *ss, exec_state_t *es, command_state_t *cs,
es_variables(es)->while_continue = false;
}

static void mod_EVERY_func(scene_state_t *ss, exec_state_t *es, command_state_t *cs,
const tele_command_t *post_command) {
int16_t mod = cs_pop(cs);
every_count_t *every = ss_get_every(ss, es_variables(es)->script_number,
es_variables(es)->line_number);
every_set_mod(every, mod);
every_tick(every);
if (every_is_now(every))
process_command(ss, es, post_command);
}

static void op_SCENE_get(const void *NOTUSED(data), scene_state_t *ss,
exec_state_t *NOTUSED(es), command_state_t *cs) {
cs_push(cs, ss->variables.scene);
@@ -9,6 +9,7 @@ extern const tele_mod_t mod_ELIF;
extern const tele_mod_t mod_ELSE;
extern const tele_mod_t mod_L;
extern const tele_mod_t mod_W;
extern const tele_mod_t mod_EVERY;

extern const tele_op_t op_SCRIPT;
extern const tele_op_t op_KILL;
@@ -160,7 +160,7 @@ const tele_op_t *tele_ops[E_OP__LENGTH] = {

const tele_mod_t *tele_mods[E_MOD__LENGTH] = {
// controlflow
&mod_IF, &mod_ELIF, &mod_ELSE, &mod_L, &mod_W, &mod_PROB,
&mod_IF, &mod_ELIF, &mod_ELSE, &mod_L, &mod_W, &mod_EVERY, &mod_PROB,

// delay
&mod_DEL,
@@ -363,6 +363,7 @@ typedef enum {
E_MOD_ELSE,
E_MOD_L,
E_MOD_W,
E_MOD_EVERY,
E_MOD_PROB,
E_MOD_DEL,
E_MOD_S,
@@ -275,6 +275,11 @@ void ss_update_script_last(scene_state_t *ss, script_number_t idx) {
ss->scripts[idx].last_time = ss->variables.time;
}

every_count_t *ss_get_every(scene_state_t *ss, script_number_t idx,
uint8_t line_number) {
return &ss->scripts[idx].every[line_number];
}

int16_t ss_turtle_get_val(scene_state_t *ss, scene_turtle_t *st) {
turtle_position_t p;
turtle_resolve_position(st, &st->position, &p);
@@ -341,6 +346,14 @@ void es_set_script_number(exec_state_t *es, uint8_t script_number) {
es_variables(es)->script_number = script_number;
}

void es_set_line_number(exec_state_t *es, uint8_t line_number) {
es_variables(es)->line_number = line_number;
}

uint8_t es_get_line_number(exec_state_t *es) {
return es_variables(es)->line_number;
}

exec_vars_t *es_variables(exec_state_t *es) {
return &es->variables[es->exec_depth - 1]; // but array is 0-indexed
}
@@ -7,6 +7,7 @@

#include "command.h"
#include "turtle.h"
#include "every.h"

#define STACK_SIZE 8
#define CV_COUNT 4
@@ -93,6 +94,7 @@ typedef struct {
uint8_t l;
tele_command_t c[SCRIPT_MAX_COMMANDS];
bool comment[SCRIPT_MAX_COMMANDS];
every_count_t every[SCRIPT_MAX_COMMANDS];
int16_t last_time;
} scene_script_t;

@@ -157,6 +159,7 @@ scene_script_t *ss_scripts_ptr(scene_state_t *ss);
size_t ss_scripts_size(void);
int16_t ss_get_script_last(scene_state_t *ss, script_number_t idx);
void ss_update_script_last(scene_state_t *ss, script_number_t idx);
every_count_t *ss_get_every(scene_state_t *ss, script_number_t idx, uint8_t line);
scene_turtle_t *ss_turtle_get(scene_state_t*);
void ss_turtle_set(scene_state_t*, scene_turtle_t*);
int16_t ss_turtle_get_val(scene_state_t*, scene_turtle_t*);
@@ -173,6 +176,7 @@ typedef struct {
uint16_t while_depth;
bool breaking;
script_number_t script_number;
uint8_t line_number;
bool delayed;
} exec_vars_t;

@@ -187,6 +191,8 @@ extern size_t es_depth(exec_state_t *es);
extern size_t es_push(exec_state_t *es);
extern size_t es_pop(exec_state_t *es);
extern void es_set_script_number(exec_state_t *es, uint8_t script_number);
extern void es_set_line_number(exec_state_t *es, uint8_t line_number);
extern uint8_t es_get_line_number(exec_state_t *es);
extern exec_vars_t *es_variables(exec_state_t *es);

////////////////////////////////////////////////////////////////////////////////
@@ -149,6 +149,8 @@ process_result_t run_script_with_exec_state(scene_state_t *ss, exec_state_t *es,
es_set_script_number(es, script_no);

for (size_t i = 0; i < ss_get_script_len(ss, script_no); i++) {
es_set_line_number(es, i);

// Commented code doesn't run.
if (ss_get_script_comment(ss, script_no, i))
continue;
@@ -7,7 +7,7 @@ tests: main.o \
parser_tests.o process_tests.o \
turtle_tests.o \
../src/teletype.o ../src/command.o ../src/helpers.o \
../src/match_token.o ../src/scanner.o \
../src/every.o ../src/match_token.o ../src/scanner.o \
../src/state.o ../src/table.o ../src/turtle.o \
../src/ops/op.o ../src/ops/ansible.c ../src/ops/controlflow.o \
../src/ops/delay.o ../src/ops/earthsea.o ../src/ops/hardware.o \

0 comments on commit 8e9c3b7

Please sign in to comment.