1
\$\begingroup\$

I have made an equivalent of Python's "eval" command in Arduino (which in itself is quite a feat) but the part that decodes the output of it is not small enough to fit in another 30 functions since this will be running on an Arduino Micro.

Any suggestions on compacting it? (btw I don't care about the actual function, rather the bit in "void Loop()" since that part is gonna be repeated a lot.)

struct evals {
  int pointer;
  bool boolout;
  String stringout;
  int intout;
  float floatout;
};
String variables[50];
String LocalVariables[50];

void setup() {
  for (int Variable = 0; Variable < 50; Variable++) {
    LocalVariables[Variable] = "";
  }
  Serial.begin(9600);
  LocalVariables[0] = "TestVariable";
  variables[0] = "true";
}
void loop() {
  if (Serial.available()) {
    String read = Serial.readString();
    evals read2 = eval(read);
    switch (read2.pointer) {
      case 0:
        Serial.println("NULL");
        break;
      case 1:
        Serial.print("INT ");
        Serial.println(read2.intout);
        break;
      case 2:
        Serial.print("FLOAT ");
        Serial.println(read2.floatout);
        break;
      case 3:
        Serial.print("STRING ");
        Serial.println(read2.stringout);
        break;
      case 4:
        Serial.print("BOOL ");
        Serial.println(read2.boolout);
        break;
      case 5:
        read2 = eval(variables[read2.intout]);
        switch (read2.pointer) {
          case 0:
            Serial.println("NULL");
            break;
          case 1:
            Serial.print("INT ");
            Serial.println(read2.intout);
            break;
          case 2:
            Serial.print("FLOAT ");
            Serial.println(read2.floatout);
            break;
          case 3:
            Serial.print("STRING ");
            Serial.println(read2.stringout);
            break;
          case 4:
            Serial.print("BOOL ");
            Serial.println(read2.boolout);
            break;
        }
    }
  }
}
struct evals eval(String input) {
  evals output;
  input.replace("\n", "");
  input.replace("\r", "");
  char input2[input.length() + 1];
  input.toCharArray(input2, input.length() + 1);
  if (input.length() == 0) {
    output.pointer = 0;
    return output;
  }
  if (input2[0] == '"' and input2[strlen(input2) - 1] == '"') {
    input.remove(0, 1);
    input.remove(strlen(input2) - 2, 1);
    output.pointer = 3;
    output.stringout = input;
    return output;
  } else if (input == "true") {
    output.pointer = 4;
    output.boolout = true;
    return output;
  } else if (input == "false") {
    output.pointer = 4;
    output.boolout = false;
    return output;
  } else {
    String inputs = input;
    inputs.replace("0", "");
    inputs.replace("1", "");
    inputs.replace("2", "");
    inputs.replace("3", "");
    inputs.replace("4", "");
    inputs.replace("5", "");
    inputs.replace("6", "");
    inputs.replace("7", "");
    inputs.replace("8", "");
    inputs.replace("9", "");
    if (inputs.length() == 0) {
      output.pointer = 1;
      output.intout = input.toInt();
      return output;
    } else {
      if (inputs[0] == '.' and inputs.length() == 1) {
        output.pointer = 2;
        output.floatout = input.toFloat();
        return output;
      } else {
        for (int Variable = 0; Variable < 50; Variable++) {
          if (LocalVariables[Variable] == "") {
            continue;
          } else if (LocalVariables[Variable] == input) {
            output.pointer = 5;
            output.intout = Variable;
            return output;
          }
        }
        output.pointer = 0;
        return output;
      }
    }
  }
}
\$\endgroup\$
1
\$\begingroup\$

I'll focus on the void loop() part as you ask it, even though it can't be reviewed in isolation, especially from the evals structure.

So, what is this loop all about? You want to select the correct behavior based on the way the evaluated data has been tagged. Which mean we have three levers to act upon: the selection mechanism, the tagging mechanism, and the way the data is represented. I believe you can do better with all three:

  • tagging your data with a char* is a bad idea. The first important thing to note is that comparing a char* with a string literal is undefined behavior. It works with most compilers, but if you enable all warnings, as you should do, you'll see it isn't guaranteed by the standard. It means that you should rely on proper string comparisons instead, character by character -e.g with strcmp- which are of course slow, if you really want to keep the string-tagging. But you don't: there are faster, simpler and more robust mechanisms such as enums.

For instance:

enum class Type : char { NULL, INTEGER, FLOATING_PRECISION, STRING, BOOL };
  • Representing your data with a struct containing as many members as there are possible types is a waste of space you should care about. You can use unions to make it more compact.

  • Selecting the correct behavior can be made in several ways, the one you chose among them. But, not wandering very far, you could have used a switch, which is arguably easier to read and can be optimized by the compiler: the program will go through the if else clauses in succession, whereas a switch can be turned into a jump-table with logarithmic look-up. If you want to explore further, and have a more scalable selection mechanism, you could have a try at a virtual function.

\$\endgroup\$
7
  • \$\begingroup\$ Thank you a lot! any std thing isn't in Arduino code sadly (i searched a lot when I was trying to use std::any), but the rest of your feedback is very much appreciated! \$\endgroup\$ – LiamBogur May 6 '19 at 10:28
  • \$\begingroup\$ Ok I have added your switch case idea, but I can't find very much documentation on how to do the rest of the stuff in Arduino, if possible could you send me some documentation? \$\endgroup\$ – LiamBogur May 6 '19 at 11:09
  • \$\begingroup\$ @LiamBogur: you're not supposed to edit your question once it has an answer -though you can answer your own question, or post another, improved question after. \$\endgroup\$ – papagaga May 6 '19 at 12:04
  • \$\begingroup\$ ok sorry, I don't really know how to use StackExchange \$\endgroup\$ – LiamBogur May 6 '19 at 12:10
  • \$\begingroup\$ @LiamBogur: what do you mean in Arduino? I assumed you were programming in C++ and targeting an Arduino device? \$\endgroup\$ – papagaga May 6 '19 at 12:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.