Skip to content

Instantly share code, notes, and snippets.

@exbotanical
Last active January 22, 2023 07:25
Show Gist options
  • Select an option

  • Save exbotanical/877fd5529cf75ac145a97d76f0c334d2 to your computer and use it in GitHub Desktop.

Select an option

Save exbotanical/877fd5529cf75ac145a97d76f0c334d2 to your computer and use it in GitHub Desktop.

Revisions

  1. exbotanical revised this gist Jan 22, 2023. 1 changed file with 6 additions and 6 deletions.
    12 changes: 6 additions & 6 deletions fsm.c
    Original file line number Diff line number Diff line change
    @@ -91,17 +91,17 @@ int main() {
    // off : {
    // transitions : {
    // switch : {
    // target:
    // 'on' action : fn
    // }
    // target: 'on'
    // action : fn
    // }
    // }
    // }
    // on : {
    // transitions : {
    // switch : {
    // target:
    // 'off' action : fn
    // }
    // target: 'off'
    // action : fn
    // }
    // }
    // }

  2. exbotanical created this gist Jan 22, 2023.
    132 changes: 132 additions & 0 deletions fsm.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,132 @@
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    typedef struct transition_t {
    char* name;
    char* target;
    void (*action)(void);
    } Transition;

    typedef struct state_t {
    char* name;
    int num_transitions;
    Transition* transitions[1];
    } StateDescriptor;

    typedef struct state_machine_t {
    char* name;
    int num_states;
    char* state;
    StateDescriptor* states[1];
    } StateMachine;

    StateDescriptor* fsm_get_state(StateMachine* fsm, char* name);

    StateMachine* fsm_create(char* name) {
    StateMachine* fsm = malloc(sizeof(*fsm));
    fsm->name = name;

    return fsm;
    }

    void fsm_register_state(StateMachine* fsm, StateDescriptor* s) {
    fsm->states[fsm->num_states] = malloc(sizeof(s));
    fsm->states[fsm->num_states++] = s;
    }

    void fsm_register_transition(StateMachine* fsm, char* state_name,
    Transition* t) {
    StateDescriptor* state = fsm_get_state(fsm, state_name);

    state->transitions[state->num_transitions] = malloc(sizeof(t));
    state->transitions[state->num_transitions++] = t;
    }

    Transition* fsm_transition_create(char* name, char* target,
    void*(action)(void)) {
    Transition* t = malloc(sizeof(*t));
    t->action = action;
    t->name = name;
    t->target = target;

    return t;
    }

    StateDescriptor* fsm_state_create(char* name) {
    StateDescriptor* s = malloc(sizeof(*s));
    s->name = name;

    return s;
    }

    StateDescriptor* fsm_get_state(StateMachine* fsm, char* name) {
    for (int i = 0; i < fsm->num_states; i++) {
    if (strcmp(fsm->states[i]->name, name) == 0) {
    return fsm->states[i];
    }
    }
    return NULL;
    }

    void fsm_transition(StateMachine* fsm, char* event) {
    StateDescriptor* s = fsm_get_state(fsm, fsm->state);

    for (int k = 0; k < s->num_transitions; k++) {
    Transition* transition = s->transitions[k];
    printf("transition\n");

    if (strcmp(transition->name, event) == 0) {
    transition->action();
    fsm->state = transition->target;
    }
    }
    }

    void off_action_handler() { printf("OFF HANDLER\n"); }
    void on_action_handler() { printf("ON HANDLER\n"); }

    int main() {
    // Let's build the following state machine
    // off : {
    // transitions : {
    // switch : {
    // target:
    // 'on' action : fn
    // }
    // }
    // }
    // on : {
    // transitions : {
    // switch : {
    // target:
    // 'off' action : fn
    // }
    // }
    // }


    StateMachine* fsm = fsm_create("test");
    fsm->state = "off";

    Transition* t1 = fsm_transition_create("switch", "on", on_action_handler);
    Transition* t2 = fsm_transition_create("switch", "off", off_action_handler);

    StateDescriptor* off_s = fsm_state_create("off");
    StateDescriptor* on_s = fsm_state_create("on");

    fsm_register_state(fsm, off_s);
    fsm_register_state(fsm, on_s);

    fsm_register_transition(fsm, off_s->name, t1);

    fsm_register_transition(fsm, on_s->name, t2);

    printf("starting state: %s\n", fsm->state);
    fsm_transition(fsm, "switch");
    printf("ending state: %s\n", fsm->state);
    fsm_transition(fsm, "switch");
    printf("ending state: %s\n", fsm->state);
    }