@@ -583,14 +583,20 @@ Value * EvalState::addConstant(const string & name, Value & v)
583583{
584584 Value * v2 = allocValue ();
585585 *v2 = v;
586- staticBaseEnv.vars [symbols.create (name)] = baseEnvDispl;
587- baseEnv.values [baseEnvDispl++] = v2;
588- string name2 = string (name, 0 , 2 ) == " __" ? string (name, 2 ) : name;
589- baseEnv.values [0 ]->attrs ->push_back (Attr (symbols.create (name2), v2));
586+ addConstant (name, v2);
590587 return v2;
591588}
592589
593590
591+ void EvalState::addConstant (const string & name, Value * v)
592+ {
593+ staticBaseEnv.vars .emplace_back (symbols.create (name), baseEnvDispl);
594+ baseEnv.values [baseEnvDispl++] = v;
595+ string name2 = string (name, 0 , 2 ) == " __" ? string (name, 2 ) : name;
596+ baseEnv.values [0 ]->attrs ->push_back (Attr (symbols.create (name2), v));
597+ }
598+
599+
594600Value * EvalState::addPrimOp (const string & name,
595601 size_t arity, PrimOpFun primOp)
596602{
@@ -609,7 +615,7 @@ Value * EvalState::addPrimOp(const string & name,
609615
610616 Value * v = allocValue ();
611617 v->mkPrimOp (new PrimOp { .fun = primOp, .arity = arity, .name = sym });
612- staticBaseEnv.vars [ symbols.create (name)] = baseEnvDispl;
618+ staticBaseEnv.vars . emplace_back ( symbols.create (name), baseEnvDispl) ;
613619 baseEnv.values [baseEnvDispl++] = v;
614620 baseEnv.values [0 ]->attrs ->push_back (Attr (sym, v));
615621 return v;
@@ -635,7 +641,7 @@ Value * EvalState::addPrimOp(PrimOp && primOp)
635641
636642 Value * v = allocValue ();
637643 v->mkPrimOp (new PrimOp (std::move (primOp)));
638- staticBaseEnv.vars [ envName] = baseEnvDispl;
644+ staticBaseEnv.vars . emplace_back ( envName, baseEnvDispl) ;
639645 baseEnv.values [baseEnvDispl++] = v;
640646 baseEnv.values [0 ]->attrs ->push_back (Attr (primOp.name , v));
641647 return v;
@@ -785,7 +791,7 @@ void mkPath(Value & v, const char * s)
785791
786792inline Value * EvalState::lookupVar (Env * env, const ExprVar & var, bool noEval)
787793{
788- for (size_t l = var.level ; l; --l, env = env->up ) ;
794+ for (auto l = var.level ; l; --l, env = env->up ) ;
789795
790796 if (!var.fromWith ) return env->values [var.displ ];
791797
@@ -1058,7 +1064,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
10581064 /* The recursive attributes are evaluated in the new
10591065 environment, while the inherited attributes are evaluated
10601066 in the original environment. */
1061- size_t displ = 0 ;
1067+ Displacement displ = 0 ;
10621068 for (auto & i : attrs) {
10631069 Value * vAttr;
10641070 if (hasOverrides && !i.second .inherited ) {
@@ -1134,7 +1140,7 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
11341140 /* The recursive attributes are evaluated in the new environment,
11351141 while the inherited attributes are evaluated in the original
11361142 environment. */
1137- size_t displ = 0 ;
1143+ Displacement displ = 0 ;
11381144 for (auto & i : attrs->attrs )
11391145 env2.values [displ++] = i.second .e ->maybeThunk (state, i.second .inherited ? env : env2);
11401146
@@ -1251,144 +1257,182 @@ void ExprLambda::eval(EvalState & state, Env & env, Value & v)
12511257}
12521258
12531259
1254- void ExprApp::eval (EvalState & state, Env & env , Value & v )
1260+ void EvalState::callFunction (Value & fun, size_t nrArgs, Value * * args , Value & vRes, const Pos & pos )
12551261{
1256- /* FIXME: vFun prevents GCC from doing tail call optimisation. */
1257- Value vFun;
1258- e1 ->eval (state, env, vFun);
1259- state.callFunction (vFun, *(e2 ->maybeThunk (state, env)), v, pos);
1260- }
1262+ auto trace = evalSettings.traceFunctionCalls ? std::make_unique<FunctionCallTrace>(pos) : nullptr ;
12611263
1264+ forceValue (fun, pos);
12621265
1263- void EvalState::callPrimOp (Value & fun, Value & arg, Value & v, const Pos & pos)
1264- {
1265- /* Figure out the number of arguments still needed. */
1266- size_t argsDone = 0 ;
1267- Value * primOp = &fun;
1268- while (primOp->isPrimOpApp ()) {
1269- argsDone++;
1270- primOp = primOp->primOpApp .left ;
1271- }
1272- assert (primOp->isPrimOp ());
1273- auto arity = primOp->primOp ->arity ;
1274- auto argsLeft = arity - argsDone;
1275-
1276- if (argsLeft == 1 ) {
1277- /* We have all the arguments, so call the primop. */
1278-
1279- /* Put all the arguments in an array. */
1280- Value * vArgs[arity];
1281- auto n = arity - 1 ;
1282- vArgs[n--] = &arg;
1283- for (Value * arg = &fun; arg->isPrimOpApp (); arg = arg->primOpApp .left )
1284- vArgs[n--] = arg->primOpApp .right ;
1285-
1286- /* And call the primop. */
1287- nrPrimOpCalls++;
1288- if (countCalls) primOpCalls[primOp->primOp ->name ]++;
1289- primOp->primOp ->fun (*this , pos, vArgs, v);
1290- } else {
1291- Value * fun2 = allocValue ();
1292- *fun2 = fun;
1293- v.mkPrimOpApp (fun2, &arg);
1294- }
1295- }
1266+ Value vCur (fun);
12961267
1297- void EvalState::callFunction (Value & fun, Value & arg, Value & v, const Pos & pos)
1298- {
1299- auto trace = evalSettings.traceFunctionCalls ? std::make_unique<FunctionCallTrace>(pos) : nullptr ;
1268+ auto makeAppChain = [&]()
1269+ {
1270+ vRes = vCur;
1271+ for (size_t i = 0 ; i < nrArgs; ++i) {
1272+ auto fun2 = allocValue ();
1273+ *fun2 = vRes;
1274+ vRes.mkPrimOpApp (fun2, args[i]);
1275+ }
1276+ };
13001277
1301- forceValue (fun, pos);
1278+ while (nrArgs > 0 ) {
13021279
1303- if (fun.isPrimOp () || fun.isPrimOpApp ()) {
1304- callPrimOp (fun, arg, v, pos);
1305- return ;
1306- }
1280+ if (vCur.isLambda ()) {
13071281
1308- if (fun.type () == nAttrs) {
1309- auto found = fun.attrs ->find (sFunctor );
1310- if (found != fun.attrs ->end ()) {
1311- /* fun may be allocated on the stack of the calling function,
1312- * but for functors we may keep a reference, so heap-allocate
1313- * a copy and use that instead.
1314- */
1315- auto & fun2 = *allocValue ();
1316- fun2 = fun;
1317- /* !!! Should we use the attr pos here? */
1318- Value v2;
1319- callFunction (*found->value , fun2, v2, pos);
1320- return callFunction (v2, arg, v, pos);
1321- }
1322- }
1282+ ExprLambda & lambda (*vCur.lambda .fun );
13231283
1324- if (!fun.isLambda ())
1325- throwTypeError (pos, " attempt to call something which is not a function but %1%" , fun);
1284+ auto size =
1285+ (lambda.arg .empty () ? 0 : 1 ) +
1286+ (lambda.hasFormals () ? lambda.formals ->formals .size () : 0 );
1287+ Env & env2 (allocEnv (size));
1288+ env2.up = vCur.lambda .env ;
13261289
1327- ExprLambda & lambda (*fun. lambda . fun ) ;
1290+ Displacement displ = 0 ;
13281291
1329- auto size =
1330- (lambda.arg .empty () ? 0 : 1 ) +
1331- (lambda.hasFormals () ? lambda.formals ->formals .size () : 0 );
1332- Env & env2 (allocEnv (size));
1333- env2.up = fun.lambda .env ;
1292+ if (!lambda.hasFormals ())
1293+ env2.values [displ++] = args[0 ];
13341294
1335- size_t displ = 0 ;
1295+ else {
1296+ forceAttrs (*args[0 ], pos);
13361297
1337- if (!lambda.hasFormals ())
1338- env2.values [displ++] = &arg ;
1298+ if (!lambda.arg . empty ())
1299+ env2.values [displ++] = args[ 0 ] ;
13391300
1340- else {
1341- forceAttrs (arg, pos);
1342-
1343- if (!lambda.arg .empty ())
1344- env2.values [displ++] = &arg;
1345-
1346- /* For each formal argument, get the actual argument. If
1347- there is no matching actual argument but the formal
1348- argument has a default, use the default. */
1349- size_t attrsUsed = 0 ;
1350- for (auto & i : lambda.formals ->formals ) {
1351- Bindings::iterator j = arg.attrs ->find (i.name );
1352- if (j == arg.attrs ->end ()) {
1353- if (!i.def ) throwTypeError (pos, " %1% called without required argument '%2%'" ,
1354- lambda, i.name );
1355- env2.values [displ++] = i.def ->maybeThunk (*this , env2);
1301+ /* For each formal argument, get the actual argument. If
1302+ there is no matching actual argument but the formal
1303+ argument has a default, use the default. */
1304+ size_t attrsUsed = 0 ;
1305+ for (auto & i : lambda.formals ->formals ) {
1306+ auto j = args[0 ]->attrs ->get (i.name );
1307+ if (!j) {
1308+ if (!i.def ) throwTypeError (pos, " %1% called without required argument '%2%'" ,
1309+ lambda, i.name );
1310+ env2.values [displ++] = i.def ->maybeThunk (*this , env2);
1311+ } else {
1312+ attrsUsed++;
1313+ env2.values [displ++] = j->value ;
1314+ }
1315+ }
1316+
1317+ /* Check that each actual argument is listed as a formal
1318+ argument (unless the attribute match specifies a `...'). */
1319+ if (!lambda.formals ->ellipsis && attrsUsed != args[0 ]->attrs ->size ()) {
1320+ /* Nope, so show the first unexpected argument to the
1321+ user. */
1322+ for (auto & i : *args[0 ]->attrs )
1323+ if (lambda.formals ->argNames .find (i.name ) == lambda.formals ->argNames .end ())
1324+ throwTypeError (pos, " %1% called with unexpected argument '%2%'" , lambda, i.name );
1325+ abort (); // can't happen
1326+ }
1327+ }
1328+
1329+ nrFunctionCalls++;
1330+ if (countCalls) incrFunctionCall (&lambda);
1331+
1332+ /* Evaluate the body. */
1333+ try {
1334+ lambda.body ->eval (*this , env2, vCur);
1335+ } catch (Error & e) {
1336+ if (loggerSettings.showTrace .get ()) {
1337+ addErrorTrace (e, lambda.pos , " while evaluating %s" ,
1338+ (lambda.name .set ()
1339+ ? " '" + (string) lambda.name + " '"
1340+ : " anonymous lambda" ));
1341+ addErrorTrace (e, pos, " from call site%s" , " " );
1342+ }
1343+ throw ;
1344+ }
1345+
1346+ nrArgs--;
1347+ args += 1 ;
1348+ }
1349+
1350+ else if (vCur.isPrimOp ()) {
1351+
1352+ size_t argsLeft = vCur.primOp ->arity ;
1353+
1354+ if (nrArgs < argsLeft) {
1355+ /* We don't have enough arguments, so create a tPrimOpApp chain. */
1356+ makeAppChain ();
1357+ return ;
1358+ } else {
1359+ /* We have all the arguments, so call the primop. */
1360+ nrPrimOpCalls++;
1361+ if (countCalls) primOpCalls[vCur.primOp ->name ]++;
1362+ vCur.primOp ->fun (*this , pos, args, vCur);
1363+
1364+ nrArgs -= argsLeft;
1365+ args += argsLeft;
1366+ }
1367+ }
1368+
1369+ else if (vCur.isPrimOpApp ()) {
1370+ /* Figure out the number of arguments still needed. */
1371+ size_t argsDone = 0 ;
1372+ Value * primOp = &vCur;
1373+ while (primOp->isPrimOpApp ()) {
1374+ argsDone++;
1375+ primOp = primOp->primOpApp .left ;
1376+ }
1377+ assert (primOp->isPrimOp ());
1378+ auto arity = primOp->primOp ->arity ;
1379+ auto argsLeft = arity - argsDone;
1380+
1381+ if (nrArgs < argsLeft) {
1382+ /* We still don't have enough arguments, so extend the tPrimOpApp chain. */
1383+ makeAppChain ();
1384+ return ;
13561385 } else {
1357- attrsUsed++;
1358- env2.values [displ++] = j->value ;
1386+ /* We have all the arguments, so call the primop with
1387+ the previous and new arguments. */
1388+
1389+ Value * vArgs[arity];
1390+ auto n = argsDone;
1391+ for (Value * arg = &vCur; arg->isPrimOpApp (); arg = arg->primOpApp .left )
1392+ vArgs[--n] = arg->primOpApp .right ;
1393+
1394+ for (size_t i = 0 ; i < argsLeft; ++i)
1395+ vArgs[argsDone + i] = args[i];
1396+
1397+ nrPrimOpCalls++;
1398+ if (countCalls) primOpCalls[primOp->primOp ->name ]++;
1399+ primOp->primOp ->fun (*this , pos, vArgs, vCur);
1400+
1401+ nrArgs -= argsLeft;
1402+ args += argsLeft;
13591403 }
13601404 }
13611405
1362- /* Check that each actual argument is listed as a formal
1363- argument (unless the attribute match specifies a `...'). */
1364- if (!lambda.formals ->ellipsis && attrsUsed != arg.attrs ->size ()) {
1365- /* Nope, so show the first unexpected argument to the
1366- user. */
1367- for (auto & i : *arg.attrs )
1368- if (lambda.formals ->argNames .find (i.name ) == lambda.formals ->argNames .end ())
1369- throwTypeError (pos, " %1% called with unexpected argument '%2%'" , lambda, i.name );
1370- abort (); // can't happen
1406+ else if (vCur.type () == nAttrs) {
1407+ if (auto functor = vCur.attrs ->get (sFunctor )) {
1408+ /* 'vCur" may be allocated on the stack of the calling
1409+ function, but for functors we may keep a reference,
1410+ so heap-allocate a copy and use that instead. */
1411+ Value * args2[] = {allocValue ()};
1412+ *args2[0 ] = vCur;
1413+ /* !!! Should we use the attr pos here? */
1414+ callFunction (*functor->value , 1 , args2, vCur, pos);
1415+ }
13711416 }
1417+
1418+ else
1419+ throwTypeError (pos, " attempt to call something which is not a function but %1%" , vCur);
13721420 }
13731421
1374- nrFunctionCalls++ ;
1375- if (countCalls) incrFunctionCall (&lambda);
1422+ vRes = vCur ;
1423+ }
13761424
1377- /* Evaluate the body. This is conditional on showTrace, because
1378- catching exceptions makes this function not tail-recursive. */
1379- if (loggerSettings.showTrace .get ())
1380- try {
1381- lambda.body ->eval (*this , env2, v);
1382- } catch (Error & e) {
1383- addErrorTrace (e, lambda.pos , " while evaluating %s" ,
1384- (lambda.name .set ()
1385- ? " '" + (string) lambda.name + " '"
1386- : " anonymous lambda" ));
1387- addErrorTrace (e, pos, " from call site%s" , " " );
1388- throw ;
1389- }
1390- else
1391- fun.lambda .fun ->body ->eval (*this , env2, v);
1425+
1426+ void ExprCall::eval (EvalState & state, Env & env, Value & v)
1427+ {
1428+ Value vFun;
1429+ fun->eval (state, env, vFun);
1430+
1431+ Value * vArgs[args.size ()];
1432+ for (size_t i = 0 ; i < args.size (); ++i)
1433+ vArgs[i] = args[i]->maybeThunk (state, env);
1434+
1435+ state.callFunction (vFun, args.size (), vArgs, v, pos);
13921436}
13931437
13941438
0 commit comments