Skip to content

Commit

Permalink
feat: expose accessor functions for control parameters (#296)
Browse files Browse the repository at this point in the history
Fixes #295
  • Loading branch information
chrispcampbell authored Dec 9, 2022
1 parent ba510b0 commit a44d097
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 2 deletions.
9 changes: 7 additions & 2 deletions packages/cli/src/c/sde.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,20 @@ EXTERN double _final_time;
EXTERN double _time_step;
EXTERN double _saveper;

// API
// API (defined in model.h)
char* run_model(const char* inputs);
void runModelWithBuffers(double* inputs, double* outputs);
void run(void);
void startOutput(void);
void outputVar(double value);
void finish(void);

// Functions implemented by the model
// API (defined by the generated model)
double getInitialTime(void);
double getFinalTime(void);
double getSaveper(void);

// Functions implemented by the generated model
void initConstants(void);
void initLevels(void);
void setInputs(const char* inputData);
Expand Down
50 changes: 50 additions & 0 deletions packages/compile/src/generate/code-gen.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ let codeGenerator = (parseTree, opts) => {
} else if (operation === 'generateC') {
// Generate code for each variable in the proper order.
let code = emitDeclCode()
code += emitGetControlValuesCode()
code += emitInitLookupsCode()
code += emitInitConstantsCode()
code += emitInitLevelsCode()
Expand Down Expand Up @@ -79,6 +80,55 @@ ${dimensionMappingsSection()}
${section(Model.lookupVars())}
${section(Model.dataVars())}
`
}

//
// Control value getters section
//
function emitGetControlValuesCode() {
function getConstTimeValue(vensimName) {
const v = Model.varWithName(Model.cName(vensimName))
if (v && v.varType === 'const') {
return v.modelFormula
} else {
throw new Error(`SDE only supports ${vensimName} defined as a constant value`)
}
}

function getSaveperValue() {
const v = Model.varWithName('_saveper')
if (v && v.varType === 'const') {
return v.modelFormula
} else if (v && v.varType === 'aux' && v.modelFormula === 'TIME STEP') {
return getConstTimeValue('TIME STEP')
} else {
throw new Error(`SDE only supports SAVEPER defined as TIME STEP or a constant value`)
}
}

// For now we only allow models that have:
// INITIAL TIME = a constant value
// FINAL TIME = a constant value
// SAVEPER = a constant value or constant `TIME STEP`
// If the model does not meet these expectations, we throw an error.
// TODO: Loosen this up to allow for certain common constant expressions
const initialTimeValue = getConstTimeValue('INITIAL TIME')
const finalTimeValue = getConstTimeValue('FINAL TIME')
const saveperValue = getSaveperValue('SAVEPER')

return `
// Control parameter accessors
double getInitialTime() {
return ${initialTimeValue};
}
double getFinalTime() {
return ${finalTimeValue};
}
double getSaveper() {
return ${saveperValue};
}
`
}

Expand Down

0 comments on commit a44d097

Please sign in to comment.