Gotchas & Tips
Common pitfalls when writing MOISSCode protocols, and how to avoid them.
Reserved Keywords
The following words are reserved by the parser and cannot be used as variable or function names:
| Keyword | Used For |
|---|---|
severity | Alert severity declaration |
protocol | Protocol definition |
input | Input declaration |
let | Variable binding |
if, else | Conditionals |
while, for, in | Loops |
track, using | KAE tracking |
assess | Clinical assessment |
alert | Clinical alerts |
administer, dose | Drug administration |
import | Module imports |
type, extends | Type definitions |
function, return | Function definitions |
true, false, null | Literals |
and, or, not | Logical operators |
// ❌ WRONG - "severity" is a keyword!
let severity = med.scores.qsofa(p);
// ✅ CORRECT - use a different name
let qsofa_score = med.scores.qsofa(p);
No Dictionary Literals
MOISSCode does not support inline dictionary/map {} syntax. Curly braces are reserved for type constructors and code blocks.
// ❌ WRONG - dict literal not supported
let result = med.lab.interpret_panel("CBC", {"WBC": 18.5, "Hgb": 8.2});
// ✅ CORRECT - use individual calls instead
let wbc = med.lab.interpret("WBC", 18.5);
let hgb = med.lab.interpret("Hgb", 8.2);
Constructor syntax IS supported:
type Isolate {
organism: str;
mic: float;
}
let iso = Isolate { organism: "E.coli", mic: 0.5 };
All Numbers Are Floats
The parser converts all numeric literals to floats, even integers like 90. If you pass a number to a library function that expects an integer (e.g., for list slicing or array indexing), the module must handle the conversion internally.
For protocol authors, this is transparent - just write numbers normally:
let sir = med.epi.sir_model(100000, 10, 0.3, 0.1, 90);
For module developers building new med.* engines in Python, always cast parameters that must be integers:
def sir_model(self, population, initial_infected, beta, gamma, days=100):
days = int(days) # Parser sends 90.0, not 90
population = int(population)
# ...
File Encoding (BOM)
When reading .moiss files programmatically (outside the CLI), use utf-8-sig encoding to handle the optional BOM (Byte Order Mark) that some editors add:
# ❌ May fail if file has BOM
with open("protocol.moiss", encoding="utf-8") as f:
code = f.read()
# ✅ Handles BOM transparently
with open("protocol.moiss", encoding="utf-8-sig") as f:
code = f.read()
The CLI's moiss run command handles this automatically.
Supported Expression Types
Function arguments in MOISSCode can only be:
| Type | Example | Notes |
|---|---|---|
| Numbers | 42, 3.14 | Always parsed as float |
| Strings | "hello" | Double-quoted |
| Booleans | true, false | Lowercase |
null | null | Null value |
| Lists | ["a", "b", "c"] | Square brackets |
| Variables | p, score | Identifiers |
| Dot access | p.hr, med.scores.qsofa(p) | Member access |
| Constructors | Type { field: val } | Custom types only |
Not supported as expressions: inline dicts {}, lambdas, ternaries.
Naming Functions and Variables
- Protocol names: PascalCase -
SepsisScreen,ICU_Admission - Variable names: snake_case -
qsofa_score,gfr_result - Function names: snake_case -
renal_stage,classify_bmi - Type names: PascalCase -
CultureResult,OutbreakReport
Import Statements
Imports are declarative only - they don't affect which modules are available. All med.* modules are always loaded. However, including them is good practice for readability:
import med.lab;
import med.nutrition;
import med.pk;