@sdeverywhere/compile 0.7.29 → 0.7.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
package/src/generate/gen-expr.js
CHANGED
|
@@ -387,6 +387,12 @@ function generateFunctionCall(callExpr, ctx) {
|
|
|
387
387
|
}
|
|
388
388
|
return generateAllocateAvailableCall(callExpr, ctx)
|
|
389
389
|
|
|
390
|
+
case '_ALLOCATE_BY_PRIORITY':
|
|
391
|
+
if (ctx.outFormat === 'js') {
|
|
392
|
+
throw new Error(`${callExpr.fnName} function not yet implemented for JS code gen`)
|
|
393
|
+
}
|
|
394
|
+
return generateAllocateByPriorityCall(callExpr, ctx)
|
|
395
|
+
|
|
390
396
|
case '_ELMCOUNT':
|
|
391
397
|
case '_SIZE': {
|
|
392
398
|
// Emit the size of the dimension in place of the dimension name. Note that Vensim uses
|
|
@@ -944,6 +950,88 @@ function generateAllocateAvailableCall(callExpr, ctx) {
|
|
|
944
950
|
return `${tmpVarId}[${allocDimId}[${allocLoopIndexVar}]]`
|
|
945
951
|
}
|
|
946
952
|
|
|
953
|
+
/**
|
|
954
|
+
* Generate C/JS code for an `ALLOCATE BY PRIORITY` function call.
|
|
955
|
+
*
|
|
956
|
+
* @param {*} callExpr The function call expression from the parsed model.
|
|
957
|
+
* @param {GenExprContext} ctx The context used when generating code for the expression.
|
|
958
|
+
* @return {string} The generated C/JS code.
|
|
959
|
+
*/
|
|
960
|
+
function generateAllocateByPriorityCall(callExpr, ctx) {
|
|
961
|
+
function validateArg(index, name) {
|
|
962
|
+
const arg = callExpr.args[index]
|
|
963
|
+
if (arg.kind === 'variable-ref') {
|
|
964
|
+
return arg
|
|
965
|
+
} else {
|
|
966
|
+
throw new Error(`ALLOCATE BY PRIORITY argument '${name}' must be a variable reference`)
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
// Given a C/JS variable reference string (e.g., '_var[i][j]'), return that
|
|
971
|
+
// string without the last N array index parts
|
|
972
|
+
function cVarRefWithoutLastIndices(arg, count) {
|
|
973
|
+
const varRef = ctx.cVarRef(arg)
|
|
974
|
+
const origIndexParts = Model.splitRefId(varRef).subscripts
|
|
975
|
+
if (origIndexParts < count) {
|
|
976
|
+
throw new Error(`ALLOCATE BY PRIORITY argument '${arg}' should have at least ${count} subscripts`)
|
|
977
|
+
}
|
|
978
|
+
const newIndexParts = origIndexParts.slice(0, -count)
|
|
979
|
+
if (newIndexParts.length > 0) {
|
|
980
|
+
return `${arg.varId}${newIndexParts.map(x => `[${x}]`).join('')}`
|
|
981
|
+
} else {
|
|
982
|
+
return arg.varId
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
// Process the request argument. Only include subscripts up until the last one;
|
|
987
|
+
// the implementation function will iterate over the requesters array.
|
|
988
|
+
const reqArg = validateArg(0, 'req')
|
|
989
|
+
const reqRef = cVarRefWithoutLastIndices(reqArg, 1)
|
|
990
|
+
|
|
991
|
+
// Process the priority argument. Only include subscripts up until the
|
|
992
|
+
// last one; the implementation function will iterate over the priorities
|
|
993
|
+
// array.
|
|
994
|
+
const priorityArg = validateArg(1, 'priority')
|
|
995
|
+
const priorityRef = cVarRefWithoutLastIndices(priorityArg, 1)
|
|
996
|
+
|
|
997
|
+
// Process the size argument
|
|
998
|
+
const sizeArg = generateExpr(callExpr.args[2], ctx)
|
|
999
|
+
|
|
1000
|
+
// Process the width argument
|
|
1001
|
+
const widthArg = generateExpr(callExpr.args[3], ctx)
|
|
1002
|
+
|
|
1003
|
+
// Process the supply argument
|
|
1004
|
+
const supplyArg = generateExpr(callExpr.args[4], ctx)
|
|
1005
|
+
|
|
1006
|
+
// The `ALLOCATE BY PRIORITY` function iterates over the last subscript in its first
|
|
1007
|
+
// argument, allocating the available quantity according to the priority values given
|
|
1008
|
+
// in the second argument. The `readEquation` process will have already verified that
|
|
1009
|
+
// the last dimension of both arguments matches the last dimension of the LHS.
|
|
1010
|
+
const allocDimId = reqArg.subscriptRefs[reqArg.subscriptRefs.length - 1].subId
|
|
1011
|
+
const allocLoopIndexVar = ctx.loopIndexVars.index(allocDimId)
|
|
1012
|
+
|
|
1013
|
+
// Generate the code that is emitted before the entire block (before any loops are opened)
|
|
1014
|
+
const tmpVarId = newTmpVarName()
|
|
1015
|
+
const numRequesters = sub(allocDimId).size
|
|
1016
|
+
switch (ctx.outFormat) {
|
|
1017
|
+
case 'c':
|
|
1018
|
+
ctx.emitPreInnerLoop(
|
|
1019
|
+
` double* ${tmpVarId} = _ALLOCATE_BY_PRIORITY(${reqRef}, ${priorityRef}, ${sizeArg}, ${widthArg}, ${supplyArg}, ${numRequesters});`
|
|
1020
|
+
)
|
|
1021
|
+
break
|
|
1022
|
+
case 'js':
|
|
1023
|
+
ctx.emitPreInnerLoop(
|
|
1024
|
+
` let ${tmpVarId} = fns.ALLOCATE_BY_PRIORITY(${reqRef}, ${priorityRef}, ${sizeArg}, ${widthArg}, ${supplyArg}, ${numRequesters});`
|
|
1025
|
+
)
|
|
1026
|
+
break
|
|
1027
|
+
default:
|
|
1028
|
+
throw new Error(`Unhandled output format '${ctx.outFormat}'`)
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
// Generate the RHS expression used in the inner loop
|
|
1032
|
+
return `${tmpVarId}[${allocDimId}[${allocLoopIndexVar}]]`
|
|
1033
|
+
}
|
|
1034
|
+
|
|
947
1035
|
/**
|
|
948
1036
|
* Recursively traverse the given expression and call the function when visiting a variable ref.
|
|
949
1037
|
*
|
|
@@ -481,6 +481,11 @@ function visitFunctionCall(v, callExpr, context) {
|
|
|
481
481
|
validateCallArgs(callExpr, 3)
|
|
482
482
|
break
|
|
483
483
|
|
|
484
|
+
case '_ALLOCATE_BY_PRIORITY':
|
|
485
|
+
validateCallDepth(callExpr, context)
|
|
486
|
+
validateCallArgs(callExpr, 5)
|
|
487
|
+
break
|
|
488
|
+
|
|
484
489
|
case '_DELAY1':
|
|
485
490
|
case '_DELAY1I':
|
|
486
491
|
case '_DELAY3':
|
|
@@ -880,6 +885,9 @@ function visitFunctionCall(v, callExpr, context) {
|
|
|
880
885
|
}
|
|
881
886
|
}
|
|
882
887
|
continue
|
|
888
|
+
} else if (callExpr.fnId === '_ALLOCATE_BY_PRIORITY') {
|
|
889
|
+
// TODO: Throw an error if the last dimension of arg0 does not match last dimension of LHS
|
|
890
|
+
// TODO: Throw an error if the last dimension of arg1 does not match last dimension of LHS
|
|
883
891
|
}
|
|
884
892
|
|
|
885
893
|
context.setArgIndex(index, argModes[index])
|