|
|
@@ -2355,1906 +2355,1919 @@ Listing:
|
|
|
2334 AND NOT SymTab.Assignable(et, ct2) THEN
|
|
|
2335 SemError(210)
|
|
|
2336 END; .)
|
|
|
- 2337 | (. IF ct2 #
|
|
|
- 2338 SymTab.InvalidType THEN
|
|
|
- 2339 SemError(233) END;
|
|
|
- 2340 astStmt := astRes; .) )
|
|
|
- 2341 | (* bare `P;`: proper parameterless
|
|
|
- 2342 procedure call; anything else
|
|
|
- 2343 here is 233 (was a bare syntax
|
|
|
- 2344 error before 4.2) *)
|
|
|
- 2345 (. astStmt := AstCallNode(astLhs);
|
|
|
- 2346 IF (dk = SymTab.KindProc)
|
|
|
- 2347 AND NOT sfx THEN
|
|
|
- 2348 res0 := SymTab.ProcRes(qn);
|
|
|
- 2349 IF res0 #
|
|
|
- 2350 SymTab.InvalidType THEN
|
|
|
- 2351 SemError(233)
|
|
|
- 2352 ELSIF SymTab.ProcNPar(qn) #
|
|
|
- 2353 0 THEN
|
|
|
- 2354 SemError(233)
|
|
|
- 2355 END
|
|
|
- 2356 ELSIF (dt # SymTab.InvalidType)
|
|
|
- 2357 AND (SymTab.ClassOf(dt) = SymTab.ClProc) THEN
|
|
|
- 2358 IF SymTab.ProcTypeRes(dt) #
|
|
|
- 2359 SymTab.InvalidType THEN
|
|
|
- 2360 SemError(233)
|
|
|
- 2361 ELSIF SymTab.ProcTypeNPar(dt) #
|
|
|
- 2362 0 THEN
|
|
|
- 2363 SemError(233)
|
|
|
- 2364 END
|
|
|
- 2365 ELSE SemError(233)
|
|
|
- 2366 END; .) ) ) .
|
|
|
- 2367 (* Actual-parameter list shared by statement and expression calls.
|
|
|
- 2368 want selects CallEnd's result handling; t/q carry the call
|
|
|
- 2369 value (statement calls discard). Arity/type failures are 233;
|
|
|
- 2370 evaluation code still emits so the .ssa stays assembleable. *)
|
|
|
- 2371 ArgList<pn: SymTab.Name; pt: SymTab.TypeIndex; callee: QbeGen.QVal;
|
|
|
- 2372 want: BOOLEAN; soft: BOOLEAN; methCls: SymTab.TypeIndex;
|
|
|
- 2373 VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
- 2374 VAR called: BOOLEAN> (. VAR i, np: CARDINAL;
|
|
|
- 2375 vs: INTEGER;
|
|
|
- 2376 res: SymTab.TypeIndex;
|
|
|
- 2377 mg: QbeGen.QVal;
|
|
|
- 2378 ok, ind, isMeth, va, isConv: BOOLEAN; .)
|
|
|
- 2379 = "(" (. called := TRUE;
|
|
|
- 2380 ok := TRUE;
|
|
|
- 2381 ind := FALSE;
|
|
|
- 2382 isConv := FALSE;
|
|
|
- 2383 isMeth := methCls #
|
|
|
- 2384 SymTab.InvalidType;
|
|
|
- 2385 IF isMeth THEN
|
|
|
- 2386 res := SymTab.ClassMethodRes(methCls, pn)
|
|
|
- 2387 ELSIF SymTab.SymKind(pn) = SymTab.KindProc THEN
|
|
|
- 2388 res := SymTab.ProcRes(pn)
|
|
|
- 2389 ELSIF (SymTab.SymKind(pn) = SymTab.KindType)
|
|
|
- 2390 OR (SymTab.SymKind(pn) = SymTab.KindPredef) THEN
|
|
|
- 2391 (* ISO type conversion T(x):
|
|
|
- 2392 one value, result is T *)
|
|
|
- 2393 isConv := TRUE;
|
|
|
- 2394 res := SymTab.SymType(pn)
|
|
|
- 2395 ELSIF (pt # SymTab.InvalidType)
|
|
|
- 2396 AND (SymTab.ClassOf(pt) = SymTab.ClProc) THEN
|
|
|
- 2397 ind := TRUE;
|
|
|
- 2398 res := SymTab.ProcTypeRes(pt)
|
|
|
- 2399 ELSE SemError(233);
|
|
|
- 2400 ok := FALSE;
|
|
|
- 2401 res := SymTab.InvalidType
|
|
|
- 2402 END;
|
|
|
- 2403 i := 0; .)
|
|
|
- 2404 [ ActParam<pn, pt, ind, methCls, i> (. INC(i); .)
|
|
|
- 2405 { "," ActParam<pn, pt, ind, methCls, i> (. INC(i); .) } ]
|
|
|
- 2406 ")" (. IF ok THEN
|
|
|
- 2407 IF isConv THEN
|
|
|
- 2408 (* a conversion takes
|
|
|
- 2409 exactly one value *)
|
|
|
- 2410 IF i # 1 THEN
|
|
|
- 2411 SemError(233); ok := FALSE
|
|
|
- 2412 END
|
|
|
- 2413 ELSE
|
|
|
- 2414 IF isMeth THEN
|
|
|
- 2415 np := SymTab.ClassMethodNPar(
|
|
|
- 2416 methCls, pn)
|
|
|
- 2417 ELSIF ind THEN
|
|
|
- 2418 np := SymTab.ProcTypeNPar(pt)
|
|
|
- 2419 ELSE np := SymTab.ProcNPar(pn)
|
|
|
- 2420 END;
|
|
|
- 2421 va := (NOT isMeth) AND (NOT ind)
|
|
|
- 2422 AND (SymTab.SymKind(pn) =
|
|
|
- 2423 SymTab.KindProc)
|
|
|
- 2424 AND SymTab.Varargs(pn);
|
|
|
- 2425 IF (i # np) AND NOT va THEN
|
|
|
- 2426 SemError(233); ok := FALSE
|
|
|
- 2427 END
|
|
|
- 2428 END
|
|
|
- 2429 END;
|
|
|
- 2430 IF NOT ok THEN
|
|
|
- 2431 t := SymTab.InvalidType;
|
|
|
- 2432 QbeGen.CopyOp("0", q)
|
|
|
- 2433 ELSIF want THEN
|
|
|
- 2434 IF res =
|
|
|
- 2435 SymTab.InvalidType THEN
|
|
|
- 2436 IF NOT soft THEN SemError(233) END;
|
|
|
- 2437 t := SymTab.InvalidType;
|
|
|
- 2438 QbeGen.CopyOp("0", q)
|
|
|
- 2439 ELSE t := res;
|
|
|
- 2440 QbeGen.CopyOp("@", q)
|
|
|
- 2441 END
|
|
|
- 2442 ELSE
|
|
|
- 2443 IF res #
|
|
|
- 2444 SymTab.InvalidType THEN
|
|
|
- 2445 SemError(233)
|
|
|
- 2446 END;
|
|
|
- 2447 t := SymTab.InvalidType;
|
|
|
- 2448 QbeGen.CopyOp("0", q);
|
|
|
- 2449 END; .) .
|
|
|
- 2450 (* One actual: VAR formals take recorded designator addresses
|
|
|
- 2451 (233 otherwise); value formals take converted expressions. *)
|
|
|
- 2452 ActParam<pn: SymTab.Name; pt: SymTab.TypeIndex; ind: BOOLEAN;
|
|
|
- 2453 methCls: SymTab.TypeIndex; i: CARDINAL>
|
|
|
- 2454 (. VAR at, ft: SymTab.TypeIndex;
|
|
|
- 2455 qe, qa, qt: QbeGen.QVal;
|
|
|
- 2456 isV, conv, va: BOOLEAN;
|
|
|
- 2457 cl: CHAR;
|
|
|
- 2458 savedN, aj: CARDINAL;
|
|
|
- 2459 savedArgs: ARRAY [0 .. 31]
|
|
|
- 2460 OF AST.Node;
|
|
|
- 2461 astActual: AST.Node; .)
|
|
|
- 2462 = (. (* Parsing the actual can clobber
|
|
|
- 2463 the enclosing call's argument
|
|
|
- 2464 list (Factor resets astNArgs),
|
|
|
- 2465 so save/restore it. *)
|
|
|
- 2466 savedN := astNArgs; aj := 0;
|
|
|
- 2467 WHILE aj <= HIGH(astArgs) DO
|
|
|
- 2468 savedArgs[aj] := astArgs[aj];
|
|
|
- 2469 INC(aj)
|
|
|
- 2470 END; .)
|
|
|
- 2471 Expr<at, qe> (. QbeGen.CopyOp(qe, convQ); convT := at;
|
|
|
- 2472 astActual := astCur;
|
|
|
- 2473 astNArgs := savedN; aj := 0;
|
|
|
- 2474 WHILE aj <= HIGH(astArgs) DO
|
|
|
- 2475 astArgs[aj] := savedArgs[aj];
|
|
|
- 2476 INC(aj)
|
|
|
- 2477 END;
|
|
|
- 2478 IF astNArgs <= HIGH(astArgs) THEN
|
|
|
- 2479 astArgs[astNArgs] := astCur;
|
|
|
- 2480 INC(astNArgs)
|
|
|
- 2481 ELSE SemError(230)
|
|
|
- 2482 (* > 32 actuals: impl limit *)
|
|
|
- 2483 END;
|
|
|
- 2484 va := (NOT ind)
|
|
|
- 2485 AND (methCls =
|
|
|
- 2486 SymTab.InvalidType)
|
|
|
- 2487 AND (SymTab.SymKind(pn) =
|
|
|
- 2488 SymTab.KindProc)
|
|
|
- 2489 AND SymTab.Varargs(pn);
|
|
|
- 2490 IF ind THEN
|
|
|
- 2491 ft :=
|
|
|
- 2492 SymTab.ProcTypeParamType(pt,
|
|
|
- 2493 i);
|
|
|
- 2494 isV :=
|
|
|
- 2495 SymTab.ProcTypeParamIsVar(pt,
|
|
|
- 2496 i)
|
|
|
- 2497 ELSIF methCls #
|
|
|
- 2498 SymTab.InvalidType THEN
|
|
|
- 2499 ft :=
|
|
|
- 2500 SymTab.ClassMethodParamType(
|
|
|
- 2501 methCls, pn, i);
|
|
|
- 2502 isV :=
|
|
|
- 2503 SymTab.ClassMethodParamIsVar(
|
|
|
- 2504 methCls, pn, i)
|
|
|
- 2505 ELSE
|
|
|
- 2506 ft := SymTab.ParamType(pn, i);
|
|
|
- 2507 isV := SymTab.ParamIsVar(pn, i)
|
|
|
- 2508 END;
|
|
|
- 2509 IF (at = SymTab.InvalidType) THEN
|
|
|
- 2510 ELSIF ft = SymTab.InvalidType THEN
|
|
|
- 2511 ELSIF isV THEN
|
|
|
- 2512 IF (SymTab.ClassOf(at) = SymTab.ClChar)
|
|
|
- 2513 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
- 2514 AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
|
|
|
- 2515 AND QbeGen.IsImm(qe) THEN
|
|
|
- 2516 ELSIF (AST.Kind(astActual) #
|
|
|
- 2517 AST.NkDesignator)
|
|
|
- 2518 AND (AST.Kind(astActual) # AST.NkStrLit) THEN
|
|
|
- 2519 SemError(233)
|
|
|
- 2520 ELSIF NOT SymTab.VarParamOk(at, ft)
|
|
|
- 2521 AND NOT SymTab.ByteBufOk(at, ft) THEN
|
|
|
- 2522 SemError(233)
|
|
|
- 2523 END
|
|
|
- 2524 ELSE
|
|
|
+ 2337 | (. (* discarding the result of a
|
|
|
+ 2338 foreign C varargs call
|
|
|
+ 2339 (printf/snprintf) is accepted;
|
|
|
+ 2340 an ordinary Modula-2 function
|
|
|
+ 2341 used as a statement stays 233 *)
|
|
|
+ 2342 IF (ct2 # SymTab.InvalidType)
|
|
|
+ 2343 AND NOT SymTab.Varargs(qn) THEN
|
|
|
+ 2344 SemError(233) END;
|
|
|
+ 2345 astStmt := astRes; .) )
|
|
|
+ 2346 | (* bare `P;`: proper parameterless
|
|
|
+ 2347 procedure call; anything else
|
|
|
+ 2348 here is 233 (was a bare syntax
|
|
|
+ 2349 error before 4.2) *)
|
|
|
+ 2350 (. astStmt := AstCallNode(astLhs);
|
|
|
+ 2351 IF (dk = SymTab.KindProc)
|
|
|
+ 2352 AND NOT sfx THEN
|
|
|
+ 2353 res0 := SymTab.ProcRes(qn);
|
|
|
+ 2354 IF res0 #
|
|
|
+ 2355 SymTab.InvalidType THEN
|
|
|
+ 2356 SemError(233)
|
|
|
+ 2357 ELSIF SymTab.ProcNPar(qn) #
|
|
|
+ 2358 0 THEN
|
|
|
+ 2359 SemError(233)
|
|
|
+ 2360 END
|
|
|
+ 2361 ELSIF (dt # SymTab.InvalidType)
|
|
|
+ 2362 AND (SymTab.ClassOf(dt) = SymTab.ClProc) THEN
|
|
|
+ 2363 IF SymTab.ProcTypeRes(dt) #
|
|
|
+ 2364 SymTab.InvalidType THEN
|
|
|
+ 2365 SemError(233)
|
|
|
+ 2366 ELSIF SymTab.ProcTypeNPar(dt) #
|
|
|
+ 2367 0 THEN
|
|
|
+ 2368 SemError(233)
|
|
|
+ 2369 END
|
|
|
+ 2370 ELSE SemError(233)
|
|
|
+ 2371 END; .) ) ) .
|
|
|
+ 2372 (* Actual-parameter list shared by statement and expression calls.
|
|
|
+ 2373 want selects CallEnd's result handling; t/q carry the call
|
|
|
+ 2374 value (statement calls discard). Arity/type failures are 233;
|
|
|
+ 2375 evaluation code still emits so the .ssa stays assembleable. *)
|
|
|
+ 2376 ArgList<pn: SymTab.Name; pt: SymTab.TypeIndex; callee: QbeGen.QVal;
|
|
|
+ 2377 want: BOOLEAN; soft: BOOLEAN; methCls: SymTab.TypeIndex;
|
|
|
+ 2378 VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
+ 2379 VAR called: BOOLEAN> (. VAR i, np: CARDINAL;
|
|
|
+ 2380 vs: INTEGER;
|
|
|
+ 2381 res: SymTab.TypeIndex;
|
|
|
+ 2382 mg: QbeGen.QVal;
|
|
|
+ 2383 ok, ind, isMeth, va, isConv: BOOLEAN; .)
|
|
|
+ 2384 = "(" (. called := TRUE;
|
|
|
+ 2385 ok := TRUE;
|
|
|
+ 2386 ind := FALSE;
|
|
|
+ 2387 isConv := FALSE;
|
|
|
+ 2388 isMeth := methCls #
|
|
|
+ 2389 SymTab.InvalidType;
|
|
|
+ 2390 IF isMeth THEN
|
|
|
+ 2391 res := SymTab.ClassMethodRes(methCls, pn)
|
|
|
+ 2392 ELSIF SymTab.SymKind(pn) = SymTab.KindProc THEN
|
|
|
+ 2393 res := SymTab.ProcRes(pn)
|
|
|
+ 2394 ELSIF (SymTab.SymKind(pn) = SymTab.KindType)
|
|
|
+ 2395 OR (SymTab.SymKind(pn) = SymTab.KindPredef) THEN
|
|
|
+ 2396 (* ISO type conversion T(x):
|
|
|
+ 2397 one value, result is T *)
|
|
|
+ 2398 isConv := TRUE;
|
|
|
+ 2399 res := SymTab.SymType(pn)
|
|
|
+ 2400 ELSIF (pt # SymTab.InvalidType)
|
|
|
+ 2401 AND (SymTab.ClassOf(pt) = SymTab.ClProc) THEN
|
|
|
+ 2402 ind := TRUE;
|
|
|
+ 2403 res := SymTab.ProcTypeRes(pt)
|
|
|
+ 2404 ELSE SemError(233);
|
|
|
+ 2405 ok := FALSE;
|
|
|
+ 2406 res := SymTab.InvalidType
|
|
|
+ 2407 END;
|
|
|
+ 2408 i := 0; .)
|
|
|
+ 2409 [ ActParam<pn, pt, ind, methCls, i> (. INC(i); .)
|
|
|
+ 2410 { "," ActParam<pn, pt, ind, methCls, i> (. INC(i); .) } ]
|
|
|
+ 2411 ")" (. IF ok THEN
|
|
|
+ 2412 IF isConv THEN
|
|
|
+ 2413 (* a conversion takes
|
|
|
+ 2414 exactly one value *)
|
|
|
+ 2415 IF i # 1 THEN
|
|
|
+ 2416 SemError(233); ok := FALSE
|
|
|
+ 2417 END
|
|
|
+ 2418 ELSE
|
|
|
+ 2419 IF isMeth THEN
|
|
|
+ 2420 np := SymTab.ClassMethodNPar(
|
|
|
+ 2421 methCls, pn)
|
|
|
+ 2422 ELSIF ind THEN
|
|
|
+ 2423 np := SymTab.ProcTypeNPar(pt)
|
|
|
+ 2424 ELSE np := SymTab.ProcNPar(pn)
|
|
|
+ 2425 END;
|
|
|
+ 2426 va := (NOT isMeth) AND (NOT ind)
|
|
|
+ 2427 AND (SymTab.SymKind(pn) =
|
|
|
+ 2428 SymTab.KindProc)
|
|
|
+ 2429 AND SymTab.Varargs(pn);
|
|
|
+ 2430 IF (i # np) AND NOT va THEN
|
|
|
+ 2431 SemError(233); ok := FALSE
|
|
|
+ 2432 END
|
|
|
+ 2433 END
|
|
|
+ 2434 END;
|
|
|
+ 2435 IF NOT ok THEN
|
|
|
+ 2436 t := SymTab.InvalidType;
|
|
|
+ 2437 QbeGen.CopyOp("0", q)
|
|
|
+ 2438 ELSIF want THEN
|
|
|
+ 2439 IF res =
|
|
|
+ 2440 SymTab.InvalidType THEN
|
|
|
+ 2441 IF NOT soft THEN SemError(233) END;
|
|
|
+ 2442 t := SymTab.InvalidType;
|
|
|
+ 2443 QbeGen.CopyOp("0", q)
|
|
|
+ 2444 ELSE t := res;
|
|
|
+ 2445 QbeGen.CopyOp("@", q)
|
|
|
+ 2446 END
|
|
|
+ 2447 ELSE
|
|
|
+ 2448 (* a function call used as
|
|
|
+ 2449 a statement: allowed for
|
|
|
+ 2450 a foreign C varargs proc
|
|
|
+ 2451 (printf/snprintf), whose
|
|
|
+ 2452 result is conventionally
|
|
|
+ 2453 discarded; ordinary
|
|
|
+ 2454 Modula-2 functions keep
|
|
|
+ 2455 the 233 diagnostic *)
|
|
|
+ 2456 IF (res # SymTab.InvalidType)
|
|
|
+ 2457 AND NOT va THEN
|
|
|
+ 2458 SemError(233)
|
|
|
+ 2459 END;
|
|
|
+ 2460 t := SymTab.InvalidType;
|
|
|
+ 2461 QbeGen.CopyOp("0", q);
|
|
|
+ 2462 END; .) .
|
|
|
+ 2463 (* One actual: VAR formals take recorded designator addresses
|
|
|
+ 2464 (233 otherwise); value formals take converted expressions. *)
|
|
|
+ 2465 ActParam<pn: SymTab.Name; pt: SymTab.TypeIndex; ind: BOOLEAN;
|
|
|
+ 2466 methCls: SymTab.TypeIndex; i: CARDINAL>
|
|
|
+ 2467 (. VAR at, ft: SymTab.TypeIndex;
|
|
|
+ 2468 qe, qa, qt: QbeGen.QVal;
|
|
|
+ 2469 isV, conv, va: BOOLEAN;
|
|
|
+ 2470 cl: CHAR;
|
|
|
+ 2471 savedN, aj: CARDINAL;
|
|
|
+ 2472 savedArgs: ARRAY [0 .. 31]
|
|
|
+ 2473 OF AST.Node;
|
|
|
+ 2474 astActual: AST.Node; .)
|
|
|
+ 2475 = (. (* Parsing the actual can clobber
|
|
|
+ 2476 the enclosing call's argument
|
|
|
+ 2477 list (Factor resets astNArgs),
|
|
|
+ 2478 so save/restore it. *)
|
|
|
+ 2479 savedN := astNArgs; aj := 0;
|
|
|
+ 2480 WHILE aj <= HIGH(astArgs) DO
|
|
|
+ 2481 savedArgs[aj] := astArgs[aj];
|
|
|
+ 2482 INC(aj)
|
|
|
+ 2483 END; .)
|
|
|
+ 2484 Expr<at, qe> (. QbeGen.CopyOp(qe, convQ); convT := at;
|
|
|
+ 2485 astActual := astCur;
|
|
|
+ 2486 astNArgs := savedN; aj := 0;
|
|
|
+ 2487 WHILE aj <= HIGH(astArgs) DO
|
|
|
+ 2488 astArgs[aj] := savedArgs[aj];
|
|
|
+ 2489 INC(aj)
|
|
|
+ 2490 END;
|
|
|
+ 2491 IF astNArgs <= HIGH(astArgs) THEN
|
|
|
+ 2492 astArgs[astNArgs] := astCur;
|
|
|
+ 2493 INC(astNArgs)
|
|
|
+ 2494 ELSE SemError(230)
|
|
|
+ 2495 (* > 32 actuals: impl limit *)
|
|
|
+ 2496 END;
|
|
|
+ 2497 va := (NOT ind)
|
|
|
+ 2498 AND (methCls =
|
|
|
+ 2499 SymTab.InvalidType)
|
|
|
+ 2500 AND (SymTab.SymKind(pn) =
|
|
|
+ 2501 SymTab.KindProc)
|
|
|
+ 2502 AND SymTab.Varargs(pn);
|
|
|
+ 2503 IF ind THEN
|
|
|
+ 2504 ft :=
|
|
|
+ 2505 SymTab.ProcTypeParamType(pt,
|
|
|
+ 2506 i);
|
|
|
+ 2507 isV :=
|
|
|
+ 2508 SymTab.ProcTypeParamIsVar(pt,
|
|
|
+ 2509 i)
|
|
|
+ 2510 ELSIF methCls #
|
|
|
+ 2511 SymTab.InvalidType THEN
|
|
|
+ 2512 ft :=
|
|
|
+ 2513 SymTab.ClassMethodParamType(
|
|
|
+ 2514 methCls, pn, i);
|
|
|
+ 2515 isV :=
|
|
|
+ 2516 SymTab.ClassMethodParamIsVar(
|
|
|
+ 2517 methCls, pn, i)
|
|
|
+ 2518 ELSE
|
|
|
+ 2519 ft := SymTab.ParamType(pn, i);
|
|
|
+ 2520 isV := SymTab.ParamIsVar(pn, i)
|
|
|
+ 2521 END;
|
|
|
+ 2522 IF (at = SymTab.InvalidType) THEN
|
|
|
+ 2523 ELSIF ft = SymTab.InvalidType THEN
|
|
|
+ 2524 ELSIF isV THEN
|
|
|
2525 IF (SymTab.ClassOf(at) = SymTab.ClChar)
|
|
|
2526 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
2527 AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
|
|
|
2528 AND QbeGen.IsImm(qe) THEN
|
|
|
- 2529 ELSIF NOT SymTab.Assignable(at, ft)
|
|
|
- 2530 AND NOT SymTab.ByteBufOk(at, ft) THEN
|
|
|
- 2531 SemError(233)
|
|
|
- 2532 END
|
|
|
- 2533 END; .) .
|
|
|
- 2534 IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 2535 q: QbeGen.QVal;
|
|
|
- 2536 hasElse: BOOLEAN;
|
|
|
- 2537 astCond, astIf, astLast,
|
|
|
- 2538 astNode: AST.Node; .)
|
|
|
- 2539 = "IF" (. hasElse := FALSE; .)
|
|
|
- 2540 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
- 2541 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 2542 SemError(214) END; .)
|
|
|
- 2543 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
- 2544 AST.SetChild(astNode, 0, astCond);
|
|
|
- 2545 AST.SetChild(astNode, 1, astStmt);
|
|
|
- 2546 astIf := astNode;
|
|
|
- 2547 astLast := astNode; .)
|
|
|
- 2548 { "ELSIF"
|
|
|
- 2549 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
- 2550 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 2551 SemError(214) END; .)
|
|
|
- 2552 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
- 2553 AST.SetChild(astNode, 0, astCond);
|
|
|
- 2554 AST.SetChild(astNode, 1, astStmt);
|
|
|
- 2555 AST.SetChild(astLast, 2, astNode);
|
|
|
- 2556 astLast := astNode; .) }
|
|
|
- 2557 [ "ELSE" (. hasElse := TRUE;
|
|
|
- 2558 astStmt := AST.NoNode; .)
|
|
|
- 2559 [ StatSeq ] (. AST.SetChild(astLast, 2, astStmt); .) ]
|
|
|
- 2560 "END" (. astStmt := astIf; .) .
|
|
|
- 2561 WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 2562 q: QbeGen.QVal;
|
|
|
- 2563 astCond, astNode: AST.Node; .)
|
|
|
- 2564 = "WHILE" (. astStmt := AST.NoNode; .)
|
|
|
- 2565 Expr<t, q> (. astCond := astCur;
|
|
|
- 2566 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 2567 SemError(214) END; .)
|
|
|
- 2568 "DO" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkWhile);
|
|
|
- 2569 AST.SetChild(astNode, 0, astCond);
|
|
|
- 2570 AST.SetChild(astNode, 1, astStmt);
|
|
|
- 2571 astStmt := astNode; .)
|
|
|
- 2572 "END" .
|
|
|
- 2573 RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 2574 q: QbeGen.QVal;
|
|
|
- 2575 astCond, astBody, astNode:
|
|
|
- 2576 AST.Node; .)
|
|
|
- 2577 = "REPEAT" (. astStmt := AST.NoNode; .)
|
|
|
- 2578 [ StatSeq ] (. astBody := astStmt; .)
|
|
|
- 2579 "UNTIL" Expr<t, q> (. astCond := astCur;
|
|
|
- 2580 astNode := AST.MakeNode(AST.NkRepeat);
|
|
|
- 2581 AST.SetChild(astNode, 0, astBody);
|
|
|
- 2582 AST.SetChild(astNode, 1, astCond);
|
|
|
- 2583 astStmt := astNode;
|
|
|
- 2584 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 2585 SemError(214) END; .) .
|
|
|
- 2586 LoopStat (. VAR lEnd: QbeGen.QVal; astNode: AST.Node; .)
|
|
|
- 2587 = "LOOP" (. astStmt := AST.NoNode;
|
|
|
- 2588 QbeGen.NewLabel(lEnd);
|
|
|
- 2589 QbeGen.PushLoop(lEnd); .)
|
|
|
- 2590 [ StatSeq ]
|
|
|
- 2591 "END" (. astNode := AST.MakeNode(AST.NkLoop);
|
|
|
- 2592 AST.SetChild(astNode, 0, astStmt);
|
|
|
- 2593 astStmt := astNode;
|
|
|
- 2594 QbeGen.PopLoop; .) .
|
|
|
- 2595 (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
|
|
|
- 2596 Runtime direction would need a compare-select; the literal
|
|
|
- 2597 sign picks cslew/csegew at "DO" time. *)
|
|
|
- 2598 ForStat (. VAR lv: SymTab.Name;
|
|
|
- 2599 tlo, thi, tby:
|
|
|
- 2600 SymTab.TypeIndex;
|
|
|
- 2601 qlo, qhi, qby, qt, qk, qb:
|
|
|
- 2602 QbeGen.QVal;
|
|
|
- 2603 lTop, lBody, lEnd:
|
|
|
- 2604 QbeGen.QVal;
|
|
|
- 2605 by: INTEGER;
|
|
|
- 2606 ok: BOOLEAN;
|
|
|
- 2607 astVar, astLo, astHi, astBy,
|
|
|
- 2608 astNode: AST.Node; .)
|
|
|
- 2609 = "FOR" (. by := 1; .)
|
|
|
- 2610 GetIdent<lv> (. astVar := AST.MakeLeaf(AST.NkIdent, lv);
|
|
|
- 2611 astStmt := AST.NoNode;
|
|
|
- 2612 astBy := AST.NoNode;
|
|
|
- 2613 ok := SymTab.Lookup(lv);
|
|
|
- 2614 IF NOT ok THEN
|
|
|
- 2615 SemError(201)
|
|
|
- 2616 ELSIF (SymTab.SymKind(lv) #
|
|
|
- 2617 SymTab.KindVar)
|
|
|
- 2618 AND (SymTab.SymKind(lv) #
|
|
|
- 2619 SymTab.KindParam) THEN
|
|
|
- 2620 SemError(220); ok := FALSE
|
|
|
- 2621 ELSIF NOT SymTab.IsOrdinal(
|
|
|
- 2622 SymTab.SymType(lv)) THEN
|
|
|
- 2623 SemError(220); ok := FALSE
|
|
|
- 2624 END; .)
|
|
|
- 2625 ":=" Expr<tlo, qlo> (. astLo := astCur;
|
|
|
- 2626 IF NOT SymTab.Assignable(tlo,
|
|
|
- 2627 SymTab.SymType(lv)) THEN
|
|
|
- 2628 SemError(220); ok := FALSE
|
|
|
- 2629 END; .)
|
|
|
- 2630 "TO" Expr<thi, qhi> (. astHi := astCur;
|
|
|
- 2631 IF NOT SymTab.Assignable(thi,
|
|
|
- 2632 SymTab.SymType(lv)) THEN
|
|
|
+ 2529 ELSIF (AST.Kind(astActual) #
|
|
|
+ 2530 AST.NkDesignator)
|
|
|
+ 2531 AND (AST.Kind(astActual) # AST.NkStrLit) THEN
|
|
|
+ 2532 SemError(233)
|
|
|
+ 2533 ELSIF NOT SymTab.VarParamOk(at, ft)
|
|
|
+ 2534 AND NOT SymTab.ByteBufOk(at, ft) THEN
|
|
|
+ 2535 SemError(233)
|
|
|
+ 2536 END
|
|
|
+ 2537 ELSE
|
|
|
+ 2538 IF (SymTab.ClassOf(at) = SymTab.ClChar)
|
|
|
+ 2539 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
+ 2540 AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
|
|
|
+ 2541 AND QbeGen.IsImm(qe) THEN
|
|
|
+ 2542 ELSIF NOT SymTab.Assignable(at, ft)
|
|
|
+ 2543 AND NOT SymTab.ByteBufOk(at, ft) THEN
|
|
|
+ 2544 SemError(233)
|
|
|
+ 2545 END
|
|
|
+ 2546 END; .) .
|
|
|
+ 2547 IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 2548 q: QbeGen.QVal;
|
|
|
+ 2549 hasElse: BOOLEAN;
|
|
|
+ 2550 astCond, astIf, astLast,
|
|
|
+ 2551 astNode: AST.Node; .)
|
|
|
+ 2552 = "IF" (. hasElse := FALSE; .)
|
|
|
+ 2553 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
+ 2554 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 2555 SemError(214) END; .)
|
|
|
+ 2556 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
+ 2557 AST.SetChild(astNode, 0, astCond);
|
|
|
+ 2558 AST.SetChild(astNode, 1, astStmt);
|
|
|
+ 2559 astIf := astNode;
|
|
|
+ 2560 astLast := astNode; .)
|
|
|
+ 2561 { "ELSIF"
|
|
|
+ 2562 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
+ 2563 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 2564 SemError(214) END; .)
|
|
|
+ 2565 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
+ 2566 AST.SetChild(astNode, 0, astCond);
|
|
|
+ 2567 AST.SetChild(astNode, 1, astStmt);
|
|
|
+ 2568 AST.SetChild(astLast, 2, astNode);
|
|
|
+ 2569 astLast := astNode; .) }
|
|
|
+ 2570 [ "ELSE" (. hasElse := TRUE;
|
|
|
+ 2571 astStmt := AST.NoNode; .)
|
|
|
+ 2572 [ StatSeq ] (. AST.SetChild(astLast, 2, astStmt); .) ]
|
|
|
+ 2573 "END" (. astStmt := astIf; .) .
|
|
|
+ 2574 WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 2575 q: QbeGen.QVal;
|
|
|
+ 2576 astCond, astNode: AST.Node; .)
|
|
|
+ 2577 = "WHILE" (. astStmt := AST.NoNode; .)
|
|
|
+ 2578 Expr<t, q> (. astCond := astCur;
|
|
|
+ 2579 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 2580 SemError(214) END; .)
|
|
|
+ 2581 "DO" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkWhile);
|
|
|
+ 2582 AST.SetChild(astNode, 0, astCond);
|
|
|
+ 2583 AST.SetChild(astNode, 1, astStmt);
|
|
|
+ 2584 astStmt := astNode; .)
|
|
|
+ 2585 "END" .
|
|
|
+ 2586 RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 2587 q: QbeGen.QVal;
|
|
|
+ 2588 astCond, astBody, astNode:
|
|
|
+ 2589 AST.Node; .)
|
|
|
+ 2590 = "REPEAT" (. astStmt := AST.NoNode; .)
|
|
|
+ 2591 [ StatSeq ] (. astBody := astStmt; .)
|
|
|
+ 2592 "UNTIL" Expr<t, q> (. astCond := astCur;
|
|
|
+ 2593 astNode := AST.MakeNode(AST.NkRepeat);
|
|
|
+ 2594 AST.SetChild(astNode, 0, astBody);
|
|
|
+ 2595 AST.SetChild(astNode, 1, astCond);
|
|
|
+ 2596 astStmt := astNode;
|
|
|
+ 2597 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 2598 SemError(214) END; .) .
|
|
|
+ 2599 LoopStat (. VAR lEnd: QbeGen.QVal; astNode: AST.Node; .)
|
|
|
+ 2600 = "LOOP" (. astStmt := AST.NoNode;
|
|
|
+ 2601 QbeGen.NewLabel(lEnd);
|
|
|
+ 2602 QbeGen.PushLoop(lEnd); .)
|
|
|
+ 2603 [ StatSeq ]
|
|
|
+ 2604 "END" (. astNode := AST.MakeNode(AST.NkLoop);
|
|
|
+ 2605 AST.SetChild(astNode, 0, astStmt);
|
|
|
+ 2606 astStmt := astNode;
|
|
|
+ 2607 QbeGen.PopLoop; .) .
|
|
|
+ 2608 (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
|
|
|
+ 2609 Runtime direction would need a compare-select; the literal
|
|
|
+ 2610 sign picks cslew/csegew at "DO" time. *)
|
|
|
+ 2611 ForStat (. VAR lv: SymTab.Name;
|
|
|
+ 2612 tlo, thi, tby:
|
|
|
+ 2613 SymTab.TypeIndex;
|
|
|
+ 2614 qlo, qhi, qby, qt, qk, qb:
|
|
|
+ 2615 QbeGen.QVal;
|
|
|
+ 2616 lTop, lBody, lEnd:
|
|
|
+ 2617 QbeGen.QVal;
|
|
|
+ 2618 by: INTEGER;
|
|
|
+ 2619 ok: BOOLEAN;
|
|
|
+ 2620 astVar, astLo, astHi, astBy,
|
|
|
+ 2621 astNode: AST.Node; .)
|
|
|
+ 2622 = "FOR" (. by := 1; .)
|
|
|
+ 2623 GetIdent<lv> (. astVar := AST.MakeLeaf(AST.NkIdent, lv);
|
|
|
+ 2624 astStmt := AST.NoNode;
|
|
|
+ 2625 astBy := AST.NoNode;
|
|
|
+ 2626 ok := SymTab.Lookup(lv);
|
|
|
+ 2627 IF NOT ok THEN
|
|
|
+ 2628 SemError(201)
|
|
|
+ 2629 ELSIF (SymTab.SymKind(lv) #
|
|
|
+ 2630 SymTab.KindVar)
|
|
|
+ 2631 AND (SymTab.SymKind(lv) #
|
|
|
+ 2632 SymTab.KindParam) THEN
|
|
|
2633 SemError(220); ok := FALSE
|
|
|
- 2634 END; .)
|
|
|
- 2635 [ "BY" Expr<tby, qby> (. astBy := astCur;
|
|
|
- 2636 IF (tby #
|
|
|
- 2637 SymTab.InvalidType)
|
|
|
- 2638 AND NOT SymTab.IsIntFamily(tby) THEN
|
|
|
- 2639 SemError(220); ok := FALSE
|
|
|
- 2640 END;
|
|
|
- 2641 IF NOT SymTab.ConstInt(qby, by) THEN
|
|
|
- 2642 SemError(230); by := 1
|
|
|
- 2643 ELSIF by = 0 THEN
|
|
|
- 2644 SemError(220); by := 1
|
|
|
- 2645 END; .) ]
|
|
|
- 2646 "DO"
|
|
|
- 2647 [ StatSeq ]
|
|
|
- 2648 "END" (. astNode := AST.MakeNode(AST.NkFor);
|
|
|
- 2649 AST.SetChild(astNode, 0, astVar);
|
|
|
- 2650 AST.SetChild(astNode, 1, astLo);
|
|
|
- 2651 AST.SetChild(astNode, 2, astHi);
|
|
|
- 2652 AST.SetChild(astNode, 3, astBy);
|
|
|
- 2653 AST.SetChild(astNode, 4, astStmt);
|
|
|
- 2654 astStmt := astNode;
|
|
|
- 2655 .) .
|
|
|
- 2656 CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
- 2657 qsel, lEnd: QbeGen.QVal;
|
|
|
- 2658 arm, astNode, astArms,
|
|
|
- 2659 astArmsTail: AST.Node; .)
|
|
|
- 2660 = "CASE" Expr<tsel, qsel> (. astNode := AST.MakeNode(AST.NkCase);
|
|
|
- 2661 AST.SetChild(astNode, 0, astCur);
|
|
|
- 2662 astArms := AST.NoNode;
|
|
|
- 2663 astArmsTail := AST.NoNode;
|
|
|
- 2664 .)
|
|
|
- 2665 "OF" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail>
|
|
|
- 2666 { "|" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail> }
|
|
|
- 2667 [ "ELSE" (. astStmt := AST.NoNode; .)
|
|
|
- 2668 [ StatSeq ] (. arm := AST.MakeNode(AST.NkCaseArm);
|
|
|
- 2669 AST.SetOp(arm, 1);
|
|
|
- 2670 AST.SetChild(arm, 0, astStmt);
|
|
|
- 2671 AstAppend(AST.NkBlock,
|
|
|
- 2672 astArms, astArmsTail, arm); .) ]
|
|
|
- 2673 "END" (. AST.SetChild(astNode, 1, astArms);
|
|
|
- 2674 astStmt := astNode;
|
|
|
- 2675 .) .
|
|
|
- 2676 (* Compare-chain lowering: each alternative ends its match-tests
|
|
|
- 2677 with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
- 2678 "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
- 2679 lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
- 2680 CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
- 2681 lEnd: QbeGen.QVal; VAR arms, armsTail: AST.Node>
|
|
|
- 2682 (. VAR arm: AST.Node; .)
|
|
|
- 2683 = (. arm := AST.MakeNode(AST.NkCaseArm); .)
|
|
|
- 2684 CaseLabel<tsel, qsel, arm>
|
|
|
- 2685 { "," CaseLabel<tsel, qsel, arm> }
|
|
|
- 2686 ":" (. astStmt := AST.NoNode; .)
|
|
|
- 2687 [ StatSeq ] (. AST.SetChild(arm, AST.NChild(arm),
|
|
|
- 2688 astStmt);
|
|
|
- 2689 AstAppend(AST.NkBlock,
|
|
|
- 2690 arms, armsTail, arm);
|
|
|
- 2691 .) .
|
|
|
- 2692 CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
- 2693 arm: AST.Node>
|
|
|
- 2694 (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
- 2695 q2, q3, qc, qd, qe:
|
|
|
- 2696 QbeGen.QVal;
|
|
|
- 2697 astLab: AST.Node;
|
|
|
- 2698 lNext: QbeGen.QVal; .)
|
|
|
- 2699 = Expr<t2, q2> (. astLab := astCur;
|
|
|
- 2700 IF SymTab.IsEmptyStr(t2)
|
|
|
- 2701 AND (SymTab.ClassOf(tsel) =
|
|
|
- 2702 SymTab.ClChar) THEN
|
|
|
- 2703 (* ISO: '' as a CASE label
|
|
|
- 2704 is the terminator *)
|
|
|
- 2705 QbeGen.CopyOp("0", q2);
|
|
|
- 2706 t2 := SymTab.CharType()
|
|
|
- 2707 END;
|
|
|
- 2708 IF (t2 #
|
|
|
- 2709 SymTab.InvalidType)
|
|
|
- 2710 AND (tsel #
|
|
|
- 2711 SymTab.InvalidType)
|
|
|
- 2712 AND NOT SymTab.EqCheck(t2,
|
|
|
- 2713 tsel) THEN
|
|
|
- 2714 SemError(213) END;
|
|
|
- 2715 (* set labels are not immediates:
|
|
|
- 2716 the CASE chain uses CmpSet *)
|
|
|
- 2717 IF (SymTab.ClassOf(t2) # SymTab.ClSet)
|
|
|
- 2718 AND NOT QbeGen.IsImm(q2) THEN
|
|
|
- 2719 SemError(230)
|
|
|
- 2720 END; .)
|
|
|
- 2721 [ ".." Expr<t3, q3> (. astLab := AST.MakeBin(
|
|
|
- 2722 AST.NkSubrange, 0, astLab, astCur);
|
|
|
- 2723 IF SymTab.IsEmptyStr(t3)
|
|
|
- 2724 AND (SymTab.ClassOf(tsel) =
|
|
|
- 2725 SymTab.ClChar) THEN
|
|
|
- 2726 QbeGen.CopyOp("0", q3);
|
|
|
- 2727 t3 := SymTab.CharType()
|
|
|
- 2728 END;
|
|
|
- 2729 IF (t3 #
|
|
|
- 2730 SymTab.InvalidType)
|
|
|
- 2731 AND (tsel #
|
|
|
- 2732 SymTab.InvalidType)
|
|
|
- 2733 AND NOT SymTab.EqCheck(t3,
|
|
|
- 2734 tsel) THEN
|
|
|
- 2735 SemError(213) END;
|
|
|
- 2736 IF (SymTab.ClassOf(t3) # SymTab.ClSet)
|
|
|
- 2737 AND NOT QbeGen.IsImm(q3) THEN
|
|
|
- 2738 SemError(230)
|
|
|
- 2739 END; .) ]
|
|
|
- 2740 (. AST.SetChild(arm,
|
|
|
- 2741 AST.NChild(arm), astLab); .) .
|
|
|
- 2742 ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 2743 q, qt: QbeGen.QVal;
|
|
|
- 2744 res: SymTab.TypeIndex;
|
|
|
- 2745 hadE, conv: BOOLEAN;
|
|
|
- 2746 astVal, astNode: AST.Node; .)
|
|
|
- 2747 = "RETURN" (. hadE := FALSE; astStmt := AST.NoNode; .)
|
|
|
- 2748 [ Expr<t, q> (. hadE := TRUE; astVal := astCur; .) ]
|
|
|
- 2749 (. astNode := AST.MakeNode(AST.NkReturn);
|
|
|
- 2750 IF hadE THEN
|
|
|
- 2751 AST.SetChild(astNode, 0, astVal)
|
|
|
- 2752 END;
|
|
|
- 2753 astStmt := astNode;
|
|
|
- 2754 conv := FALSE;
|
|
|
- 2755 IF NOT SymTab.InProc() THEN
|
|
|
- 2756 SemError(232)
|
|
|
- 2757 ELSE res := SymTab.CurRes();
|
|
|
- 2758 IF NOT hadE THEN
|
|
|
- 2759 IF res #
|
|
|
- 2760 SymTab.InvalidType THEN
|
|
|
- 2761 SemError(232)
|
|
|
- 2762 END
|
|
|
- 2763 ELSIF (res =
|
|
|
- 2764 SymTab.InvalidType)
|
|
|
- 2765 OR (t #
|
|
|
- 2766 SymTab.InvalidType)
|
|
|
- 2767 AND NOT SymTab.Assignable(t,
|
|
|
- 2768 res) THEN
|
|
|
- 2769 SemError(232)
|
|
|
- 2770 END
|
|
|
- 2771 END; .) .
|
|
|
- 2772 HaltStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 2773 q: QbeGen.QVal;
|
|
|
- 2774 astVal, astNode: AST.Node; .)
|
|
|
- 2775 = "HALT" (. astVal := AST.NoNode; .)
|
|
|
- 2776 [ "(" Expr<t, q> (. astVal := astCur; .) ")" ]
|
|
|
- 2777 (. astNode := AST.MakeNode(AST.NkHalt);
|
|
|
- 2778 IF astVal # AST.NoNode THEN
|
|
|
- 2779 AST.SetChild(astNode, 0, astVal)
|
|
|
- 2780 END;
|
|
|
- 2781 astStmt := astNode;
|
|
|
- 2782 .) .
|
|
|
- 2783 (* Designator: scalar loads, array addresses, and index suffixes.
|
|
|
- 2784 Each index descends one level (bounds-checked, trap on breach);
|
|
|
- 2785 nested levels reload the inner descriptor address. q ends as the
|
|
|
- 2786 value (scalars), the descriptor address (plain arrays), or the
|
|
|
- 2787 element address (indexed); sfx marks the indexed form. *)
|
|
|
- 2788 Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
- 2789 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
- 2790 (. VAR n: SymTab.Name; .)
|
|
|
- 2791 = GetIdent<n> DesignTail<n, t, k, q, qn, sfx> .
|
|
|
- 2792 (* The part of Design after the identifier: resolve it and walk the
|
|
|
- 2793 selectors. Split out so a statement can decide between a label
|
|
|
- 2794 (`ident :`) and a designator (`ident := ...`) with one token. *)
|
|
|
- 2795 DesignTail<VAR n: SymTab.Name; VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
- 2796 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
- 2797 (. VAR fn, mal: SymTab.Name;
|
|
|
- 2798 cls: INTEGER;
|
|
|
- 2799 ic: SymTab.TypeIndex;
|
|
|
- 2800 curT, it, eT, bt:
|
|
|
- 2801 SymTab.TypeIndex;
|
|
|
- 2802 iq, ql, qlo, qhi, qe:
|
|
|
- 2803 QbeGen.QVal;
|
|
|
- 2804 lo, hi: INTEGER;
|
|
|
- 2805 fo: INTEGER;
|
|
|
- 2806 isOpen: BOOLEAN;
|
|
|
- 2807 qb, cv: QbeGen.QVal;
|
|
|
- 2808 r: BOOLEAN;
|
|
|
- 2809 astDes, astSel: AST.Node; .)
|
|
|
- 2810 = (. methCls := SymTab.InvalidType;
|
|
|
- 2811 QbeGen.CopyOp(n, qn);
|
|
|
- 2812 sfx := FALSE;
|
|
|
- 2813 IF NOT SymTab.Lookup(n) THEN
|
|
|
- 2814 (* a bare method name inside
|
|
|
- 2815 a CLASS IMPLEMENTATION
|
|
|
- 2816 is a sibling call on
|
|
|
- 2817 THIS *)
|
|
|
- 2818 ic := SymTab.CurImplClass();
|
|
|
- 2819 IF (ic #
|
|
|
- 2820 SymTab.InvalidType)
|
|
|
- 2821 AND SymTab.MethodExists(ic, n) THEN
|
|
|
- 2822 sfx := FALSE;
|
|
|
- 2823 QbeGen.CopyOp("@", q);
|
|
|
- 2824 methCls := ic;
|
|
|
- 2825 k := SymTab.KindProc;
|
|
|
- 2826 t := SymTab.InvalidType
|
|
|
- 2827 ELSIF SymTab.InProc() THEN
|
|
|
- 2828 (* not declared anywhere
|
|
|
- 2829 in scope: with bodies
|
|
|
- 2830 parsed at unit end this
|
|
|
- 2831 is a genuine 201 (a
|
|
|
- 2832 nested-local forward is
|
|
|
- 2833 no longer tolerated). *)
|
|
|
- 2834 SemError(201);
|
|
|
- 2835 t := SymTab.InvalidType;
|
|
|
- 2836 k := -1;
|
|
|
- 2837 QbeGen.CopyOp("0", q)
|
|
|
- 2838 ELSE
|
|
|
- 2839 SemError(201);
|
|
|
- 2840 t :=
|
|
|
- 2841 SymTab.InvalidType;
|
|
|
- 2842 k := -1;
|
|
|
- 2843 QbeGen.CopyOp("0", q)
|
|
|
- 2844 END
|
|
|
- 2845 ELSE
|
|
|
- 2846 t := SymTab.SymType(n);
|
|
|
- 2847 k := SymTab.SymKind(n);
|
|
|
- 2848 IF k = SymTab.KindConst THEN
|
|
|
- 2849 IF SymTab.Equal(n,
|
|
|
- 2850 "TRUE") THEN
|
|
|
- 2851 t := SymTab.BoolType();
|
|
|
- 2852 QbeGen.CopyOp("1", q)
|
|
|
- 2853 ELSIF SymTab.Equal(n,
|
|
|
- 2854 "FALSE") THEN
|
|
|
- 2855 t := SymTab.BoolType();
|
|
|
- 2856 QbeGen.CopyOp("0", q)
|
|
|
- 2857 ELSIF SymTab.Equal(n,
|
|
|
- 2858 "NIL") THEN
|
|
|
- 2859 QbeGen.CopyOp("0", q)
|
|
|
- 2860 ELSE
|
|
|
- 2861 cls :=
|
|
|
- 2862 SymTab.ClassOf(t);
|
|
|
- 2863 IF (t #
|
|
|
- 2864 SymTab.InvalidType)
|
|
|
- 2865 AND ((cls = SymTab.ClInt)
|
|
|
- 2866 OR (cls
|
|
|
- 2867 = SymTab.ClChar)
|
|
|
- 2868 OR (cls
|
|
|
- 2869 = SymTab.ClEnum)
|
|
|
- 2870 OR (cls
|
|
|
- 2871 = SymTab.ClReal)
|
|
|
- 2872 OR (cls
|
|
|
- 2873 = SymTab.ClLong)
|
|
|
- 2874 OR (cls
|
|
|
- 2875 = SymTab.ClNil)
|
|
|
- 2876 OR (cls = SymTab.ClBool)) THEN
|
|
|
- 2877 IF cls = SymTab.ClNil THEN
|
|
|
- 2878 QbeGen.CopyOp("0", q)
|
|
|
- 2879 ELSIF ((cls
|
|
|
- 2880 = SymTab.ClInt)
|
|
|
- 2881 OR (cls
|
|
|
- 2882 = SymTab.ClChar)
|
|
|
- 2883 OR (cls
|
|
|
- 2884 = SymTab.ClEnum)
|
|
|
- 2885 OR (cls
|
|
|
- 2886 = SymTab.ClLong)
|
|
|
- 2887 OR (cls = SymTab.ClBool))
|
|
|
- 2888 AND SymTab.GetSymVal(n, cv)
|
|
|
- 2889 AND QbeGen.IsImm(cv) THEN
|
|
|
- 2890 QbeGen.CopyOp(cv, q)
|
|
|
- 2891 ELSE
|
|
|
- 2892 QbeGen.LoadVar(n,
|
|
|
- 2893 cls = SymTab.ClReal,
|
|
|
- 2894 q)
|
|
|
- 2895 END
|
|
|
- 2896 ELSIF (cls = SymTab.ClArray)
|
|
|
- 2897 OR (cls = SymTab.ClRecord)
|
|
|
- 2898 OR (cls = SymTab.ClClass)
|
|
|
- 2899 OR (cls = SymTab.ClStr)
|
|
|
- 2900 OR (cls = SymTab.ClUStr)
|
|
|
- 2901 OR (cls = SymTab.ClSet) THEN
|
|
|
- 2902 (* aggregate constant:
|
|
|
- 2903 its value IS the
|
|
|
- 2904 descriptor address *)
|
|
|
- 2905 IF SymTab.GetSymVal(n, cv) THEN
|
|
|
- 2906 QbeGen.CopyOp(cv, q)
|
|
|
- 2907 ELSE
|
|
|
- 2908 QbeGen.CopyOp("0", q)
|
|
|
- 2909 END
|
|
|
- 2910 ELSE
|
|
|
- 2911 IF t #
|
|
|
- 2912 SymTab.InvalidType THEN
|
|
|
- 2913 SemError(230)
|
|
|
- 2914 END;
|
|
|
- 2915 QbeGen.CopyOp("0", q)
|
|
|
- 2916 END
|
|
|
- 2917 END
|
|
|
- 2918 ELSIF (k = SymTab.KindVar)
|
|
|
- 2919 OR (k = SymTab.KindParam) THEN
|
|
|
- 2920 cls := SymTab.ClassOf(t);
|
|
|
- 2921 IF (cls # SymTab.ClInt)
|
|
|
- 2922 AND (cls # SymTab.ClBool)
|
|
|
- 2923 AND (cls # SymTab.ClChar)
|
|
|
- 2924 AND (cls # SymTab.ClUChar)
|
|
|
- 2925 AND (cls # SymTab.ClEnum)
|
|
|
- 2926 AND (cls # SymTab.ClReal)
|
|
|
- 2927 AND (cls # SymTab.ClPtr)
|
|
|
- 2928 AND (cls # SymTab.ClProc)
|
|
|
- 2929 AND (cls # SymTab.ClLong)
|
|
|
- 2930 AND (cls # SymTab.ClArray)
|
|
|
- 2931 AND (cls # SymTab.ClSet)
|
|
|
- 2932 AND (cls # SymTab.ClRecord)
|
|
|
- 2933 AND (cls # SymTab.ClUStr)
|
|
|
- 2934 AND (cls # SymTab.ClClass) THEN
|
|
|
- 2935 SemError(230);
|
|
|
- 2936 QbeGen.CopyOp("0", q)
|
|
|
- 2937 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 2938 END
|
|
|
- 2939 ELSE QbeGen.CopyOp("0", q);
|
|
|
- 2940 IF k = SymTab.KindImport THEN
|
|
|
- 2941 SemError(230)
|
|
|
- 2942 ELSIF k =
|
|
|
- 2943 SymTab.KindProc THEN
|
|
|
- 2944 (* bare procedure name:
|
|
|
- 2945 a following ArgList
|
|
|
- 2946 makes it a call;
|
|
|
- 2947 otherwise Fact
|
|
|
- 2948 reports 230 *)
|
|
|
- 2949 ELSE
|
|
|
- 2950 IF k = SymTab.KindField THEN
|
|
|
- 2951 IF QbeGen.TopWith(qb) THEN
|
|
|
- 2952 sfx := TRUE
|
|
|
- 2953 ELSE SemError(230);
|
|
|
- 2954 QbeGen.CopyOp("0", q)
|
|
|
- 2955 END
|
|
|
- 2956 END
|
|
|
- 2957 END
|
|
|
- 2958 END
|
|
|
- 2959 END; .)
|
|
|
- 2960 (. astDes := AST.MakeNode(AST.NkDesignator);
|
|
|
- 2961 AST.SetChild(astDes, AST.NChild(astDes), AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
- 2962 { "[" Expr<it, iq>
|
|
|
- 2963 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
- 2964 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
- 2965 ELSIF SymTab.ClassOf(t) #
|
|
|
- 2966 SymTab.ClArray THEN
|
|
|
- 2967 SemError(217);
|
|
|
- 2968 t := SymTab.InvalidType
|
|
|
- 2969 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
- 2970 AND (SymTab.ClassOf(it) #
|
|
|
- 2971 SymTab.ClChar)
|
|
|
- 2972 AND (SymTab.ClassOf(it) #
|
|
|
- 2973 SymTab.ClEnum)
|
|
|
- 2974 AND (SymTab.ClassOf(it) #
|
|
|
- 2975 SymTab.ClBool) THEN
|
|
|
- 2976 SemError(218);
|
|
|
- 2977 t := SymTab.InvalidType
|
|
|
- 2978 ELSE
|
|
|
- 2979 eT := SymTab.ArrayElem(t);
|
|
|
- 2980 t := eT; sfx := TRUE
|
|
|
- 2981 END; .)
|
|
|
- 2982 { "," Expr<it, iq>
|
|
|
- 2983 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
- 2984 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
- 2985 ELSIF SymTab.ClassOf(t) #
|
|
|
- 2986 SymTab.ClArray THEN
|
|
|
- 2987 SemError(217);
|
|
|
- 2988 t := SymTab.InvalidType
|
|
|
- 2989 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
- 2990 AND (SymTab.ClassOf(it) #
|
|
|
- 2991 SymTab.ClChar)
|
|
|
- 2992 AND (SymTab.ClassOf(it) #
|
|
|
- 2993 SymTab.ClEnum)
|
|
|
- 2994 AND (SymTab.ClassOf(it) #
|
|
|
- 2995 SymTab.ClBool) THEN
|
|
|
- 2996 SemError(218);
|
|
|
- 2997 t := SymTab.InvalidType
|
|
|
- 2998 ELSE
|
|
|
- 2999 eT := SymTab.ArrayElem(t);
|
|
|
- 3000 t := eT; sfx := TRUE
|
|
|
- 3001 END; .) }
|
|
|
- 3002 "]"
|
|
|
- 3003 | "." GetIdent<fn>
|
|
|
- 3004 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
- 3005 AST.SetOp(astSel, AST.SelField);
|
|
|
- 3006 AST.SetChild(astSel, 0, AST.MakeLeaf(AST.NkIdent, fn));
|
|
|
- 3007 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF k = SymTab.KindModule THEN
|
|
|
- 3008 (* qualified L.x: materialize
|
|
|
- 3009 the export, then load it *)
|
|
|
- 3010 IF NOT SymTab.MaterializeAlias(n,
|
|
|
- 3011 fn, mal) THEN
|
|
|
- 3012 SemError(201);
|
|
|
- 3013 t := SymTab.InvalidType;
|
|
|
- 3014 QbeGen.CopyOp("0", q)
|
|
|
- 3015 ELSE
|
|
|
- 3016 QbeGen.CopyOp(mal, qn);
|
|
|
- 3017 t := SymTab.SymType(mal);
|
|
|
- 3018 k := SymTab.SymKind(mal);
|
|
|
- 3019 sfx := FALSE;
|
|
|
- 3020 IF k = SymTab.KindProc THEN
|
|
|
- 3021 (* call: ArgList supplies
|
|
|
- 3022 the value *)
|
|
|
- 3023 QbeGen.CopyOp("0", q)
|
|
|
- 3024 ELSIF k = SymTab.KindConst THEN
|
|
|
- 3025 IF SymTab.GetSymVal(mal,
|
|
|
- 3026 cv)
|
|
|
- 3027 THEN QbeGen.CopyOp(cv, q)
|
|
|
- 3028 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 3029 END
|
|
|
- 3030 END
|
|
|
- 3031 END
|
|
|
- 3032 ELSIF t = SymTab.InvalidType THEN
|
|
|
- 3033 ELSIF (SymTab.ClassOf(t) #
|
|
|
- 3034 SymTab.ClRecord)
|
|
|
- 3035 AND (SymTab.ClassOf(t) #
|
|
|
- 3036 SymTab.ClClass) THEN
|
|
|
- 3037 SemError(215);
|
|
|
- 3038 t := SymTab.InvalidType
|
|
|
- 3039 ELSIF (SymTab.ClassOf(t) =
|
|
|
- 3040 SymTab.ClClass)
|
|
|
- 3041 AND SymTab.MethodExists(t, fn) THEN
|
|
|
- 3042 (* obj.Method: bind the
|
|
|
- 3043 method and pass obj as
|
|
|
- 3044 the hidden receiver; q
|
|
|
- 3045 already holds the
|
|
|
- 3046 object's address *)
|
|
|
- 3047 QbeGen.CopyOp(fn, n);
|
|
|
- 3048 QbeGen.CopyOp(fn, qn);
|
|
|
- 3049 methCls := t;
|
|
|
- 3050 k := SymTab.KindProc;
|
|
|
+ 2634 ELSIF NOT SymTab.IsOrdinal(
|
|
|
+ 2635 SymTab.SymType(lv)) THEN
|
|
|
+ 2636 SemError(220); ok := FALSE
|
|
|
+ 2637 END; .)
|
|
|
+ 2638 ":=" Expr<tlo, qlo> (. astLo := astCur;
|
|
|
+ 2639 IF NOT SymTab.Assignable(tlo,
|
|
|
+ 2640 SymTab.SymType(lv)) THEN
|
|
|
+ 2641 SemError(220); ok := FALSE
|
|
|
+ 2642 END; .)
|
|
|
+ 2643 "TO" Expr<thi, qhi> (. astHi := astCur;
|
|
|
+ 2644 IF NOT SymTab.Assignable(thi,
|
|
|
+ 2645 SymTab.SymType(lv)) THEN
|
|
|
+ 2646 SemError(220); ok := FALSE
|
|
|
+ 2647 END; .)
|
|
|
+ 2648 [ "BY" Expr<tby, qby> (. astBy := astCur;
|
|
|
+ 2649 IF (tby #
|
|
|
+ 2650 SymTab.InvalidType)
|
|
|
+ 2651 AND NOT SymTab.IsIntFamily(tby) THEN
|
|
|
+ 2652 SemError(220); ok := FALSE
|
|
|
+ 2653 END;
|
|
|
+ 2654 IF NOT SymTab.ConstInt(qby, by) THEN
|
|
|
+ 2655 SemError(230); by := 1
|
|
|
+ 2656 ELSIF by = 0 THEN
|
|
|
+ 2657 SemError(220); by := 1
|
|
|
+ 2658 END; .) ]
|
|
|
+ 2659 "DO"
|
|
|
+ 2660 [ StatSeq ]
|
|
|
+ 2661 "END" (. astNode := AST.MakeNode(AST.NkFor);
|
|
|
+ 2662 AST.SetChild(astNode, 0, astVar);
|
|
|
+ 2663 AST.SetChild(astNode, 1, astLo);
|
|
|
+ 2664 AST.SetChild(astNode, 2, astHi);
|
|
|
+ 2665 AST.SetChild(astNode, 3, astBy);
|
|
|
+ 2666 AST.SetChild(astNode, 4, astStmt);
|
|
|
+ 2667 astStmt := astNode;
|
|
|
+ 2668 .) .
|
|
|
+ 2669 CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
+ 2670 qsel, lEnd: QbeGen.QVal;
|
|
|
+ 2671 arm, astNode, astArms,
|
|
|
+ 2672 astArmsTail: AST.Node; .)
|
|
|
+ 2673 = "CASE" Expr<tsel, qsel> (. astNode := AST.MakeNode(AST.NkCase);
|
|
|
+ 2674 AST.SetChild(astNode, 0, astCur);
|
|
|
+ 2675 astArms := AST.NoNode;
|
|
|
+ 2676 astArmsTail := AST.NoNode;
|
|
|
+ 2677 .)
|
|
|
+ 2678 "OF" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail>
|
|
|
+ 2679 { "|" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail> }
|
|
|
+ 2680 [ "ELSE" (. astStmt := AST.NoNode; .)
|
|
|
+ 2681 [ StatSeq ] (. arm := AST.MakeNode(AST.NkCaseArm);
|
|
|
+ 2682 AST.SetOp(arm, 1);
|
|
|
+ 2683 AST.SetChild(arm, 0, astStmt);
|
|
|
+ 2684 AstAppend(AST.NkBlock,
|
|
|
+ 2685 astArms, astArmsTail, arm); .) ]
|
|
|
+ 2686 "END" (. AST.SetChild(astNode, 1, astArms);
|
|
|
+ 2687 astStmt := astNode;
|
|
|
+ 2688 .) .
|
|
|
+ 2689 (* Compare-chain lowering: each alternative ends its match-tests
|
|
|
+ 2690 with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
+ 2691 "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
+ 2692 lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
+ 2693 CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
+ 2694 lEnd: QbeGen.QVal; VAR arms, armsTail: AST.Node>
|
|
|
+ 2695 (. VAR arm: AST.Node; .)
|
|
|
+ 2696 = (. arm := AST.MakeNode(AST.NkCaseArm); .)
|
|
|
+ 2697 CaseLabel<tsel, qsel, arm>
|
|
|
+ 2698 { "," CaseLabel<tsel, qsel, arm> }
|
|
|
+ 2699 ":" (. astStmt := AST.NoNode; .)
|
|
|
+ 2700 [ StatSeq ] (. AST.SetChild(arm, AST.NChild(arm),
|
|
|
+ 2701 astStmt);
|
|
|
+ 2702 AstAppend(AST.NkBlock,
|
|
|
+ 2703 arms, armsTail, arm);
|
|
|
+ 2704 .) .
|
|
|
+ 2705 CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
+ 2706 arm: AST.Node>
|
|
|
+ 2707 (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
+ 2708 q2, q3, qc, qd, qe:
|
|
|
+ 2709 QbeGen.QVal;
|
|
|
+ 2710 astLab: AST.Node;
|
|
|
+ 2711 lNext: QbeGen.QVal; .)
|
|
|
+ 2712 = Expr<t2, q2> (. astLab := astCur;
|
|
|
+ 2713 IF SymTab.IsEmptyStr(t2)
|
|
|
+ 2714 AND (SymTab.ClassOf(tsel) =
|
|
|
+ 2715 SymTab.ClChar) THEN
|
|
|
+ 2716 (* ISO: '' as a CASE label
|
|
|
+ 2717 is the terminator *)
|
|
|
+ 2718 QbeGen.CopyOp("0", q2);
|
|
|
+ 2719 t2 := SymTab.CharType()
|
|
|
+ 2720 END;
|
|
|
+ 2721 IF (t2 #
|
|
|
+ 2722 SymTab.InvalidType)
|
|
|
+ 2723 AND (tsel #
|
|
|
+ 2724 SymTab.InvalidType)
|
|
|
+ 2725 AND NOT SymTab.EqCheck(t2,
|
|
|
+ 2726 tsel) THEN
|
|
|
+ 2727 SemError(213) END;
|
|
|
+ 2728 (* set labels are not immediates:
|
|
|
+ 2729 the CASE chain uses CmpSet *)
|
|
|
+ 2730 IF (SymTab.ClassOf(t2) # SymTab.ClSet)
|
|
|
+ 2731 AND NOT QbeGen.IsImm(q2) THEN
|
|
|
+ 2732 SemError(230)
|
|
|
+ 2733 END; .)
|
|
|
+ 2734 [ ".." Expr<t3, q3> (. astLab := AST.MakeBin(
|
|
|
+ 2735 AST.NkSubrange, 0, astLab, astCur);
|
|
|
+ 2736 IF SymTab.IsEmptyStr(t3)
|
|
|
+ 2737 AND (SymTab.ClassOf(tsel) =
|
|
|
+ 2738 SymTab.ClChar) THEN
|
|
|
+ 2739 QbeGen.CopyOp("0", q3);
|
|
|
+ 2740 t3 := SymTab.CharType()
|
|
|
+ 2741 END;
|
|
|
+ 2742 IF (t3 #
|
|
|
+ 2743 SymTab.InvalidType)
|
|
|
+ 2744 AND (tsel #
|
|
|
+ 2745 SymTab.InvalidType)
|
|
|
+ 2746 AND NOT SymTab.EqCheck(t3,
|
|
|
+ 2747 tsel) THEN
|
|
|
+ 2748 SemError(213) END;
|
|
|
+ 2749 IF (SymTab.ClassOf(t3) # SymTab.ClSet)
|
|
|
+ 2750 AND NOT QbeGen.IsImm(q3) THEN
|
|
|
+ 2751 SemError(230)
|
|
|
+ 2752 END; .) ]
|
|
|
+ 2753 (. AST.SetChild(arm,
|
|
|
+ 2754 AST.NChild(arm), astLab); .) .
|
|
|
+ 2755 ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 2756 q, qt: QbeGen.QVal;
|
|
|
+ 2757 res: SymTab.TypeIndex;
|
|
|
+ 2758 hadE, conv: BOOLEAN;
|
|
|
+ 2759 astVal, astNode: AST.Node; .)
|
|
|
+ 2760 = "RETURN" (. hadE := FALSE; astStmt := AST.NoNode; .)
|
|
|
+ 2761 [ Expr<t, q> (. hadE := TRUE; astVal := astCur; .) ]
|
|
|
+ 2762 (. astNode := AST.MakeNode(AST.NkReturn);
|
|
|
+ 2763 IF hadE THEN
|
|
|
+ 2764 AST.SetChild(astNode, 0, astVal)
|
|
|
+ 2765 END;
|
|
|
+ 2766 astStmt := astNode;
|
|
|
+ 2767 conv := FALSE;
|
|
|
+ 2768 IF NOT SymTab.InProc() THEN
|
|
|
+ 2769 SemError(232)
|
|
|
+ 2770 ELSE res := SymTab.CurRes();
|
|
|
+ 2771 IF NOT hadE THEN
|
|
|
+ 2772 IF res #
|
|
|
+ 2773 SymTab.InvalidType THEN
|
|
|
+ 2774 SemError(232)
|
|
|
+ 2775 END
|
|
|
+ 2776 ELSIF (res =
|
|
|
+ 2777 SymTab.InvalidType)
|
|
|
+ 2778 OR (t #
|
|
|
+ 2779 SymTab.InvalidType)
|
|
|
+ 2780 AND NOT SymTab.Assignable(t,
|
|
|
+ 2781 res) THEN
|
|
|
+ 2782 SemError(232)
|
|
|
+ 2783 END
|
|
|
+ 2784 END; .) .
|
|
|
+ 2785 HaltStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 2786 q: QbeGen.QVal;
|
|
|
+ 2787 astVal, astNode: AST.Node; .)
|
|
|
+ 2788 = "HALT" (. astVal := AST.NoNode; .)
|
|
|
+ 2789 [ "(" Expr<t, q> (. astVal := astCur; .) ")" ]
|
|
|
+ 2790 (. astNode := AST.MakeNode(AST.NkHalt);
|
|
|
+ 2791 IF astVal # AST.NoNode THEN
|
|
|
+ 2792 AST.SetChild(astNode, 0, astVal)
|
|
|
+ 2793 END;
|
|
|
+ 2794 astStmt := astNode;
|
|
|
+ 2795 .) .
|
|
|
+ 2796 (* Designator: scalar loads, array addresses, and index suffixes.
|
|
|
+ 2797 Each index descends one level (bounds-checked, trap on breach);
|
|
|
+ 2798 nested levels reload the inner descriptor address. q ends as the
|
|
|
+ 2799 value (scalars), the descriptor address (plain arrays), or the
|
|
|
+ 2800 element address (indexed); sfx marks the indexed form. *)
|
|
|
+ 2801 Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
+ 2802 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
+ 2803 (. VAR n: SymTab.Name; .)
|
|
|
+ 2804 = GetIdent<n> DesignTail<n, t, k, q, qn, sfx> .
|
|
|
+ 2805 (* The part of Design after the identifier: resolve it and walk the
|
|
|
+ 2806 selectors. Split out so a statement can decide between a label
|
|
|
+ 2807 (`ident :`) and a designator (`ident := ...`) with one token. *)
|
|
|
+ 2808 DesignTail<VAR n: SymTab.Name; VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
+ 2809 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
+ 2810 (. VAR fn, mal: SymTab.Name;
|
|
|
+ 2811 cls: INTEGER;
|
|
|
+ 2812 ic: SymTab.TypeIndex;
|
|
|
+ 2813 curT, it, eT, bt:
|
|
|
+ 2814 SymTab.TypeIndex;
|
|
|
+ 2815 iq, ql, qlo, qhi, qe:
|
|
|
+ 2816 QbeGen.QVal;
|
|
|
+ 2817 lo, hi: INTEGER;
|
|
|
+ 2818 fo: INTEGER;
|
|
|
+ 2819 isOpen: BOOLEAN;
|
|
|
+ 2820 qb, cv: QbeGen.QVal;
|
|
|
+ 2821 r: BOOLEAN;
|
|
|
+ 2822 astDes, astSel: AST.Node; .)
|
|
|
+ 2823 = (. methCls := SymTab.InvalidType;
|
|
|
+ 2824 QbeGen.CopyOp(n, qn);
|
|
|
+ 2825 sfx := FALSE;
|
|
|
+ 2826 IF NOT SymTab.Lookup(n) THEN
|
|
|
+ 2827 (* a bare method name inside
|
|
|
+ 2828 a CLASS IMPLEMENTATION
|
|
|
+ 2829 is a sibling call on
|
|
|
+ 2830 THIS *)
|
|
|
+ 2831 ic := SymTab.CurImplClass();
|
|
|
+ 2832 IF (ic #
|
|
|
+ 2833 SymTab.InvalidType)
|
|
|
+ 2834 AND SymTab.MethodExists(ic, n) THEN
|
|
|
+ 2835 sfx := FALSE;
|
|
|
+ 2836 QbeGen.CopyOp("@", q);
|
|
|
+ 2837 methCls := ic;
|
|
|
+ 2838 k := SymTab.KindProc;
|
|
|
+ 2839 t := SymTab.InvalidType
|
|
|
+ 2840 ELSIF SymTab.InProc() THEN
|
|
|
+ 2841 (* not declared anywhere
|
|
|
+ 2842 in scope: with bodies
|
|
|
+ 2843 parsed at unit end this
|
|
|
+ 2844 is a genuine 201 (a
|
|
|
+ 2845 nested-local forward is
|
|
|
+ 2846 no longer tolerated). *)
|
|
|
+ 2847 SemError(201);
|
|
|
+ 2848 t := SymTab.InvalidType;
|
|
|
+ 2849 k := -1;
|
|
|
+ 2850 QbeGen.CopyOp("0", q)
|
|
|
+ 2851 ELSE
|
|
|
+ 2852 SemError(201);
|
|
|
+ 2853 t :=
|
|
|
+ 2854 SymTab.InvalidType;
|
|
|
+ 2855 k := -1;
|
|
|
+ 2856 QbeGen.CopyOp("0", q)
|
|
|
+ 2857 END
|
|
|
+ 2858 ELSE
|
|
|
+ 2859 t := SymTab.SymType(n);
|
|
|
+ 2860 k := SymTab.SymKind(n);
|
|
|
+ 2861 IF k = SymTab.KindConst THEN
|
|
|
+ 2862 IF SymTab.Equal(n,
|
|
|
+ 2863 "TRUE") THEN
|
|
|
+ 2864 t := SymTab.BoolType();
|
|
|
+ 2865 QbeGen.CopyOp("1", q)
|
|
|
+ 2866 ELSIF SymTab.Equal(n,
|
|
|
+ 2867 "FALSE") THEN
|
|
|
+ 2868 t := SymTab.BoolType();
|
|
|
+ 2869 QbeGen.CopyOp("0", q)
|
|
|
+ 2870 ELSIF SymTab.Equal(n,
|
|
|
+ 2871 "NIL") THEN
|
|
|
+ 2872 QbeGen.CopyOp("0", q)
|
|
|
+ 2873 ELSE
|
|
|
+ 2874 cls :=
|
|
|
+ 2875 SymTab.ClassOf(t);
|
|
|
+ 2876 IF (t #
|
|
|
+ 2877 SymTab.InvalidType)
|
|
|
+ 2878 AND ((cls = SymTab.ClInt)
|
|
|
+ 2879 OR (cls
|
|
|
+ 2880 = SymTab.ClChar)
|
|
|
+ 2881 OR (cls
|
|
|
+ 2882 = SymTab.ClEnum)
|
|
|
+ 2883 OR (cls
|
|
|
+ 2884 = SymTab.ClReal)
|
|
|
+ 2885 OR (cls
|
|
|
+ 2886 = SymTab.ClLong)
|
|
|
+ 2887 OR (cls
|
|
|
+ 2888 = SymTab.ClNil)
|
|
|
+ 2889 OR (cls = SymTab.ClBool)) THEN
|
|
|
+ 2890 IF cls = SymTab.ClNil THEN
|
|
|
+ 2891 QbeGen.CopyOp("0", q)
|
|
|
+ 2892 ELSIF ((cls
|
|
|
+ 2893 = SymTab.ClInt)
|
|
|
+ 2894 OR (cls
|
|
|
+ 2895 = SymTab.ClChar)
|
|
|
+ 2896 OR (cls
|
|
|
+ 2897 = SymTab.ClEnum)
|
|
|
+ 2898 OR (cls
|
|
|
+ 2899 = SymTab.ClLong)
|
|
|
+ 2900 OR (cls = SymTab.ClBool))
|
|
|
+ 2901 AND SymTab.GetSymVal(n, cv)
|
|
|
+ 2902 AND QbeGen.IsImm(cv) THEN
|
|
|
+ 2903 QbeGen.CopyOp(cv, q)
|
|
|
+ 2904 ELSE
|
|
|
+ 2905 QbeGen.LoadVar(n,
|
|
|
+ 2906 cls = SymTab.ClReal,
|
|
|
+ 2907 q)
|
|
|
+ 2908 END
|
|
|
+ 2909 ELSIF (cls = SymTab.ClArray)
|
|
|
+ 2910 OR (cls = SymTab.ClRecord)
|
|
|
+ 2911 OR (cls = SymTab.ClClass)
|
|
|
+ 2912 OR (cls = SymTab.ClStr)
|
|
|
+ 2913 OR (cls = SymTab.ClUStr)
|
|
|
+ 2914 OR (cls = SymTab.ClSet) THEN
|
|
|
+ 2915 (* aggregate constant:
|
|
|
+ 2916 its value IS the
|
|
|
+ 2917 descriptor address *)
|
|
|
+ 2918 IF SymTab.GetSymVal(n, cv) THEN
|
|
|
+ 2919 QbeGen.CopyOp(cv, q)
|
|
|
+ 2920 ELSE
|
|
|
+ 2921 QbeGen.CopyOp("0", q)
|
|
|
+ 2922 END
|
|
|
+ 2923 ELSE
|
|
|
+ 2924 IF t #
|
|
|
+ 2925 SymTab.InvalidType THEN
|
|
|
+ 2926 SemError(230)
|
|
|
+ 2927 END;
|
|
|
+ 2928 QbeGen.CopyOp("0", q)
|
|
|
+ 2929 END
|
|
|
+ 2930 END
|
|
|
+ 2931 ELSIF (k = SymTab.KindVar)
|
|
|
+ 2932 OR (k = SymTab.KindParam) THEN
|
|
|
+ 2933 cls := SymTab.ClassOf(t);
|
|
|
+ 2934 IF (cls # SymTab.ClInt)
|
|
|
+ 2935 AND (cls # SymTab.ClBool)
|
|
|
+ 2936 AND (cls # SymTab.ClChar)
|
|
|
+ 2937 AND (cls # SymTab.ClUChar)
|
|
|
+ 2938 AND (cls # SymTab.ClEnum)
|
|
|
+ 2939 AND (cls # SymTab.ClReal)
|
|
|
+ 2940 AND (cls # SymTab.ClPtr)
|
|
|
+ 2941 AND (cls # SymTab.ClProc)
|
|
|
+ 2942 AND (cls # SymTab.ClLong)
|
|
|
+ 2943 AND (cls # SymTab.ClArray)
|
|
|
+ 2944 AND (cls # SymTab.ClSet)
|
|
|
+ 2945 AND (cls # SymTab.ClRecord)
|
|
|
+ 2946 AND (cls # SymTab.ClUStr)
|
|
|
+ 2947 AND (cls # SymTab.ClClass) THEN
|
|
|
+ 2948 SemError(230);
|
|
|
+ 2949 QbeGen.CopyOp("0", q)
|
|
|
+ 2950 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 2951 END
|
|
|
+ 2952 ELSE QbeGen.CopyOp("0", q);
|
|
|
+ 2953 IF k = SymTab.KindImport THEN
|
|
|
+ 2954 SemError(230)
|
|
|
+ 2955 ELSIF k =
|
|
|
+ 2956 SymTab.KindProc THEN
|
|
|
+ 2957 (* bare procedure name:
|
|
|
+ 2958 a following ArgList
|
|
|
+ 2959 makes it a call;
|
|
|
+ 2960 otherwise Fact
|
|
|
+ 2961 reports 230 *)
|
|
|
+ 2962 ELSE
|
|
|
+ 2963 IF k = SymTab.KindField THEN
|
|
|
+ 2964 IF QbeGen.TopWith(qb) THEN
|
|
|
+ 2965 sfx := TRUE
|
|
|
+ 2966 ELSE SemError(230);
|
|
|
+ 2967 QbeGen.CopyOp("0", q)
|
|
|
+ 2968 END
|
|
|
+ 2969 END
|
|
|
+ 2970 END
|
|
|
+ 2971 END
|
|
|
+ 2972 END; .)
|
|
|
+ 2973 (. astDes := AST.MakeNode(AST.NkDesignator);
|
|
|
+ 2974 AST.SetChild(astDes, AST.NChild(astDes), AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
+ 2975 { "[" Expr<it, iq>
|
|
|
+ 2976 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
+ 2977 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
+ 2978 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2979 SymTab.ClArray THEN
|
|
|
+ 2980 SemError(217);
|
|
|
+ 2981 t := SymTab.InvalidType
|
|
|
+ 2982 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
+ 2983 AND (SymTab.ClassOf(it) #
|
|
|
+ 2984 SymTab.ClChar)
|
|
|
+ 2985 AND (SymTab.ClassOf(it) #
|
|
|
+ 2986 SymTab.ClEnum)
|
|
|
+ 2987 AND (SymTab.ClassOf(it) #
|
|
|
+ 2988 SymTab.ClBool) THEN
|
|
|
+ 2989 SemError(218);
|
|
|
+ 2990 t := SymTab.InvalidType
|
|
|
+ 2991 ELSE
|
|
|
+ 2992 eT := SymTab.ArrayElem(t);
|
|
|
+ 2993 t := eT; sfx := TRUE
|
|
|
+ 2994 END; .)
|
|
|
+ 2995 { "," Expr<it, iq>
|
|
|
+ 2996 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
+ 2997 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
+ 2998 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2999 SymTab.ClArray THEN
|
|
|
+ 3000 SemError(217);
|
|
|
+ 3001 t := SymTab.InvalidType
|
|
|
+ 3002 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
+ 3003 AND (SymTab.ClassOf(it) #
|
|
|
+ 3004 SymTab.ClChar)
|
|
|
+ 3005 AND (SymTab.ClassOf(it) #
|
|
|
+ 3006 SymTab.ClEnum)
|
|
|
+ 3007 AND (SymTab.ClassOf(it) #
|
|
|
+ 3008 SymTab.ClBool) THEN
|
|
|
+ 3009 SemError(218);
|
|
|
+ 3010 t := SymTab.InvalidType
|
|
|
+ 3011 ELSE
|
|
|
+ 3012 eT := SymTab.ArrayElem(t);
|
|
|
+ 3013 t := eT; sfx := TRUE
|
|
|
+ 3014 END; .) }
|
|
|
+ 3015 "]"
|
|
|
+ 3016 | "." GetIdent<fn>
|
|
|
+ 3017 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
+ 3018 AST.SetOp(astSel, AST.SelField);
|
|
|
+ 3019 AST.SetChild(astSel, 0, AST.MakeLeaf(AST.NkIdent, fn));
|
|
|
+ 3020 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF k = SymTab.KindModule THEN
|
|
|
+ 3021 (* qualified L.x: materialize
|
|
|
+ 3022 the export, then load it *)
|
|
|
+ 3023 IF NOT SymTab.MaterializeAlias(n,
|
|
|
+ 3024 fn, mal) THEN
|
|
|
+ 3025 SemError(201);
|
|
|
+ 3026 t := SymTab.InvalidType;
|
|
|
+ 3027 QbeGen.CopyOp("0", q)
|
|
|
+ 3028 ELSE
|
|
|
+ 3029 QbeGen.CopyOp(mal, qn);
|
|
|
+ 3030 t := SymTab.SymType(mal);
|
|
|
+ 3031 k := SymTab.SymKind(mal);
|
|
|
+ 3032 sfx := FALSE;
|
|
|
+ 3033 IF k = SymTab.KindProc THEN
|
|
|
+ 3034 (* call: ArgList supplies
|
|
|
+ 3035 the value *)
|
|
|
+ 3036 QbeGen.CopyOp("0", q)
|
|
|
+ 3037 ELSIF k = SymTab.KindConst THEN
|
|
|
+ 3038 IF SymTab.GetSymVal(mal,
|
|
|
+ 3039 cv)
|
|
|
+ 3040 THEN QbeGen.CopyOp(cv, q)
|
|
|
+ 3041 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 3042 END
|
|
|
+ 3043 END
|
|
|
+ 3044 END
|
|
|
+ 3045 ELSIF t = SymTab.InvalidType THEN
|
|
|
+ 3046 ELSIF (SymTab.ClassOf(t) #
|
|
|
+ 3047 SymTab.ClRecord)
|
|
|
+ 3048 AND (SymTab.ClassOf(t) #
|
|
|
+ 3049 SymTab.ClClass) THEN
|
|
|
+ 3050 SemError(215);
|
|
|
3051 t := SymTab.InvalidType
|
|
|
- 3052 ELSIF NOT SymTab.FieldExists(t,
|
|
|
- 3053 fn) THEN
|
|
|
- 3054 SemError(216);
|
|
|
- 3055 t := SymTab.InvalidType
|
|
|
- 3056 ELSE
|
|
|
- 3057 t := SymTab.FieldType(t, fn);
|
|
|
- 3058 sfx := TRUE
|
|
|
- 3059 END; .)
|
|
|
- 3060 | "^"
|
|
|
- 3061 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
- 3062 AST.SetOp(astSel, AST.SelDeref);
|
|
|
- 3063 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF t = SymTab.InvalidType THEN
|
|
|
- 3064 ELSIF SymTab.ClassOf(t) #
|
|
|
- 3065 SymTab.ClPtr THEN
|
|
|
- 3066 SemError(219);
|
|
|
- 3067 t := SymTab.InvalidType
|
|
|
- 3068 ELSE
|
|
|
- 3069 bt := SymTab.PtrBase(t);
|
|
|
- 3070 IF bt = SymTab.InvalidType THEN
|
|
|
- 3071 ELSE
|
|
|
- 3072 t := bt;
|
|
|
- 3073 sfx := TRUE
|
|
|
- 3074 END
|
|
|
- 3075 END; .) } (. astCur := astDes; .) .
|
|
|
- 3076 (* Result suffix (ISO component after a function call): `F()^`,
|
|
|
- 3077 `F()[i]`, `F().field`. The call result is in t/q with sfx FALSE
|
|
|
- 3078 (a value, or a descriptor address for aggregates); each component
|
|
|
- 3079 descends one level exactly like the Design components. *)
|
|
|
- 3080 ResultComp<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
- 3081 VAR sfx: BOOLEAN; VAR node: AST.Node;
|
|
|
- 3082 VAR mname: SymTab.Name; VAR methCls: SymTab.TypeIndex;
|
|
|
- 3083 VAR isM: BOOLEAN> (. VAR it, eT, bt: SymTab.TypeIndex;
|
|
|
- 3084 iq, ql, qlo, qhi, qe, qb:
|
|
|
- 3085 QbeGen.QVal;
|
|
|
- 3086 lo, hi, fo: INTEGER;
|
|
|
- 3087 isOpen: BOOLEAN;
|
|
|
- 3088 fname: SymTab.Name;
|
|
|
- 3089 astWrap, astSel: AST.Node; .)
|
|
|
- 3090 = "[" Expr<it, iq>
|
|
|
- 3091 (. isM := FALSE;
|
|
|
- 3092 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
- 3093 astWrap := AST.MakeNode(
|
|
|
- 3094 AST.NkDesignator);
|
|
|
- 3095 AST.SetChild(astWrap, 0, node);
|
|
|
- 3096 node := astWrap
|
|
|
- 3097 END;
|
|
|
- 3098 AST.SetChild(node, AST.NChild(node),
|
|
|
- 3099 AST.MakeUn(AST.NkSelector,
|
|
|
- 3100 AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
- 3101 ELSIF SymTab.ClassOf(t) #
|
|
|
- 3102 SymTab.ClArray THEN
|
|
|
- 3103 SemError(217);
|
|
|
- 3104 t := SymTab.InvalidType
|
|
|
- 3105 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
- 3106 AND (SymTab.ClassOf(it) # SymTab.ClChar)
|
|
|
- 3107 AND (SymTab.ClassOf(it) # SymTab.ClEnum)
|
|
|
- 3108 AND (SymTab.ClassOf(it) # SymTab.ClBool) THEN
|
|
|
- 3109 SemError(218);
|
|
|
- 3110 t := SymTab.InvalidType
|
|
|
- 3111 ELSE
|
|
|
- 3112 eT := SymTab.ArrayElem(t);
|
|
|
- 3113 t := eT; sfx := TRUE
|
|
|
- 3114 END; .)
|
|
|
- 3115 "]"
|
|
|
- 3116 | "." GetIdent<fname>
|
|
|
- 3117 (. isM := FALSE;
|
|
|
- 3118 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
- 3119 astWrap := AST.MakeNode(
|
|
|
- 3120 AST.NkDesignator);
|
|
|
- 3121 AST.SetChild(astWrap, 0, node);
|
|
|
- 3122 node := astWrap
|
|
|
- 3123 END;
|
|
|
- 3124 AST.SetChild(node, AST.NChild(node),
|
|
|
- 3125 AST.MakeUn(AST.NkSelector,
|
|
|
- 3126 AST.SelField,
|
|
|
- 3127 AST.MakeLeaf(AST.NkIdent,
|
|
|
- 3128 fname))); IF t = SymTab.InvalidType THEN
|
|
|
- 3129 ELSIF (SymTab.ClassOf(t) #
|
|
|
- 3130 SymTab.ClRecord)
|
|
|
- 3131 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
- 3132 SemError(215);
|
|
|
- 3133 t := SymTab.InvalidType
|
|
|
- 3134 ELSIF (SymTab.ClassOf(t) =
|
|
|
- 3135 SymTab.ClClass)
|
|
|
- 3136 AND SymTab.MethodExists(t, fname) THEN
|
|
|
- 3137 (* a method on the call result:
|
|
|
- 3138 a following ArgList makes
|
|
|
- 3139 the call *)
|
|
|
- 3140 mname := fname;
|
|
|
- 3141 methCls := t; isM := TRUE;
|
|
|
- 3142 t := SymTab.InvalidType
|
|
|
- 3143 ELSIF NOT SymTab.FieldExists(t,
|
|
|
- 3144 fname) THEN
|
|
|
- 3145 SemError(216);
|
|
|
+ 3052 ELSIF (SymTab.ClassOf(t) =
|
|
|
+ 3053 SymTab.ClClass)
|
|
|
+ 3054 AND SymTab.MethodExists(t, fn) THEN
|
|
|
+ 3055 (* obj.Method: bind the
|
|
|
+ 3056 method and pass obj as
|
|
|
+ 3057 the hidden receiver; q
|
|
|
+ 3058 already holds the
|
|
|
+ 3059 object's address *)
|
|
|
+ 3060 QbeGen.CopyOp(fn, n);
|
|
|
+ 3061 QbeGen.CopyOp(fn, qn);
|
|
|
+ 3062 methCls := t;
|
|
|
+ 3063 k := SymTab.KindProc;
|
|
|
+ 3064 t := SymTab.InvalidType
|
|
|
+ 3065 ELSIF NOT SymTab.FieldExists(t,
|
|
|
+ 3066 fn) THEN
|
|
|
+ 3067 SemError(216);
|
|
|
+ 3068 t := SymTab.InvalidType
|
|
|
+ 3069 ELSE
|
|
|
+ 3070 t := SymTab.FieldType(t, fn);
|
|
|
+ 3071 sfx := TRUE
|
|
|
+ 3072 END; .)
|
|
|
+ 3073 | "^"
|
|
|
+ 3074 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
+ 3075 AST.SetOp(astSel, AST.SelDeref);
|
|
|
+ 3076 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF t = SymTab.InvalidType THEN
|
|
|
+ 3077 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 3078 SymTab.ClPtr THEN
|
|
|
+ 3079 SemError(219);
|
|
|
+ 3080 t := SymTab.InvalidType
|
|
|
+ 3081 ELSE
|
|
|
+ 3082 bt := SymTab.PtrBase(t);
|
|
|
+ 3083 IF bt = SymTab.InvalidType THEN
|
|
|
+ 3084 ELSE
|
|
|
+ 3085 t := bt;
|
|
|
+ 3086 sfx := TRUE
|
|
|
+ 3087 END
|
|
|
+ 3088 END; .) } (. astCur := astDes; .) .
|
|
|
+ 3089 (* Result suffix (ISO component after a function call): `F()^`,
|
|
|
+ 3090 `F()[i]`, `F().field`. The call result is in t/q with sfx FALSE
|
|
|
+ 3091 (a value, or a descriptor address for aggregates); each component
|
|
|
+ 3092 descends one level exactly like the Design components. *)
|
|
|
+ 3093 ResultComp<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
+ 3094 VAR sfx: BOOLEAN; VAR node: AST.Node;
|
|
|
+ 3095 VAR mname: SymTab.Name; VAR methCls: SymTab.TypeIndex;
|
|
|
+ 3096 VAR isM: BOOLEAN> (. VAR it, eT, bt: SymTab.TypeIndex;
|
|
|
+ 3097 iq, ql, qlo, qhi, qe, qb:
|
|
|
+ 3098 QbeGen.QVal;
|
|
|
+ 3099 lo, hi, fo: INTEGER;
|
|
|
+ 3100 isOpen: BOOLEAN;
|
|
|
+ 3101 fname: SymTab.Name;
|
|
|
+ 3102 astWrap, astSel: AST.Node; .)
|
|
|
+ 3103 = "[" Expr<it, iq>
|
|
|
+ 3104 (. isM := FALSE;
|
|
|
+ 3105 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
+ 3106 astWrap := AST.MakeNode(
|
|
|
+ 3107 AST.NkDesignator);
|
|
|
+ 3108 AST.SetChild(astWrap, 0, node);
|
|
|
+ 3109 node := astWrap
|
|
|
+ 3110 END;
|
|
|
+ 3111 AST.SetChild(node, AST.NChild(node),
|
|
|
+ 3112 AST.MakeUn(AST.NkSelector,
|
|
|
+ 3113 AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
+ 3114 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 3115 SymTab.ClArray THEN
|
|
|
+ 3116 SemError(217);
|
|
|
+ 3117 t := SymTab.InvalidType
|
|
|
+ 3118 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
+ 3119 AND (SymTab.ClassOf(it) # SymTab.ClChar)
|
|
|
+ 3120 AND (SymTab.ClassOf(it) # SymTab.ClEnum)
|
|
|
+ 3121 AND (SymTab.ClassOf(it) # SymTab.ClBool) THEN
|
|
|
+ 3122 SemError(218);
|
|
|
+ 3123 t := SymTab.InvalidType
|
|
|
+ 3124 ELSE
|
|
|
+ 3125 eT := SymTab.ArrayElem(t);
|
|
|
+ 3126 t := eT; sfx := TRUE
|
|
|
+ 3127 END; .)
|
|
|
+ 3128 "]"
|
|
|
+ 3129 | "." GetIdent<fname>
|
|
|
+ 3130 (. isM := FALSE;
|
|
|
+ 3131 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
+ 3132 astWrap := AST.MakeNode(
|
|
|
+ 3133 AST.NkDesignator);
|
|
|
+ 3134 AST.SetChild(astWrap, 0, node);
|
|
|
+ 3135 node := astWrap
|
|
|
+ 3136 END;
|
|
|
+ 3137 AST.SetChild(node, AST.NChild(node),
|
|
|
+ 3138 AST.MakeUn(AST.NkSelector,
|
|
|
+ 3139 AST.SelField,
|
|
|
+ 3140 AST.MakeLeaf(AST.NkIdent,
|
|
|
+ 3141 fname))); IF t = SymTab.InvalidType THEN
|
|
|
+ 3142 ELSIF (SymTab.ClassOf(t) #
|
|
|
+ 3143 SymTab.ClRecord)
|
|
|
+ 3144 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
+ 3145 SemError(215);
|
|
|
3146 t := SymTab.InvalidType
|
|
|
- 3147 ELSE
|
|
|
- 3148 t := SymTab.FieldType(t, fname);
|
|
|
- 3149 sfx := TRUE
|
|
|
- 3150 END; .)
|
|
|
- 3151 | "^" (. isM := FALSE;
|
|
|
- 3152 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
- 3153 astWrap := AST.MakeNode(
|
|
|
- 3154 AST.NkDesignator);
|
|
|
- 3155 AST.SetChild(astWrap, 0, node);
|
|
|
- 3156 node := astWrap
|
|
|
- 3157 END;
|
|
|
- 3158 astSel := AST.MakeNode(AST.NkSelector);
|
|
|
- 3159 AST.SetOp(astSel, AST.SelDeref);
|
|
|
- 3160 AST.SetChild(node,
|
|
|
- 3161 AST.NChild(node), astSel); IF t = SymTab.InvalidType THEN
|
|
|
- 3162 ELSIF SymTab.ClassOf(t) #
|
|
|
- 3163 SymTab.ClPtr THEN
|
|
|
- 3164 SemError(219);
|
|
|
- 3165 t := SymTab.InvalidType
|
|
|
- 3166 ELSE
|
|
|
- 3167 bt := SymTab.PtrBase(t);
|
|
|
- 3168 IF bt # SymTab.InvalidType THEN
|
|
|
- 3169 t := bt; sfx := TRUE
|
|
|
- 3170 END
|
|
|
- 3171 END; .) .
|
|
|
- 3172 Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 3173 (. VAR t2: SymTab.TypeIndex;
|
|
|
- 3174 op: INTEGER;
|
|
|
- 3175 q2, qt, wl: QbeGen.QVal;
|
|
|
- 3176 astA, astB: AST.Node;
|
|
|
- 3177 astOp: INTEGER;
|
|
|
- 3178 astMade: BOOLEAN;
|
|
|
- 3179 isR: BOOLEAN; .)
|
|
|
- 3180 = SimExpr<t, q> (. astA := astCur; astMade := FALSE; .)
|
|
|
- 3181 [ Rel<op> SimExpr<t2, q2>
|
|
|
- 3182 (. astB := astCur; astMade := TRUE;
|
|
|
- 3183 astOp := AST.OpEq;
|
|
|
- 3184 IF op = SymTab.OpNeq1 THEN astOp := AST.OpNe
|
|
|
- 3185 ELSIF op = SymTab.OpNeq2 THEN astOp := AST.OpNe
|
|
|
- 3186 ELSIF op = SymTab.OpLt THEN astOp := AST.OpLt
|
|
|
- 3187 ELSIF op = SymTab.OpLe THEN astOp := AST.OpLe
|
|
|
- 3188 ELSIF op = SymTab.OpGt THEN astOp := AST.OpGt
|
|
|
- 3189 ELSIF op = SymTab.OpGe THEN astOp := AST.OpGe
|
|
|
- 3190 ELSIF op = SymTab.OpIn THEN astOp := AST.OpIn
|
|
|
- 3191 END;
|
|
|
- 3192 IF op = SymTab.OpIn THEN
|
|
|
- 3193 IF SymTab.InCheck(t, t2) THEN
|
|
|
- 3194 IF (t = SymTab.InvalidType)
|
|
|
- 3195 OR (t2 = SymTab.InvalidType) THEN
|
|
|
- 3196 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
- 3197 ELSE
|
|
|
- 3198 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
- 3199 END
|
|
|
- 3200 ELSE SemError(222); t := SymTab.InvalidType;
|
|
|
- 3201 QbeGen.CopyOp("0", q)
|
|
|
- 3202 END
|
|
|
- 3203 ELSIF SymTab.RelCheck(t, t2, op) THEN
|
|
|
- 3204 IF (t = SymTab.InvalidType)
|
|
|
- 3205 OR (t2 = SymTab.InvalidType) THEN
|
|
|
- 3206 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
- 3207 ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
|
|
|
- 3208 OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
|
|
|
- 3209 IF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
|
|
|
- 3210 AND (op # SymTab.OpNeq2) THEN
|
|
|
- 3211 SemError(213); t := SymTab.InvalidType;
|
|
|
- 3212 QbeGen.CopyOp("0", q)
|
|
|
- 3213 ELSE
|
|
|
- 3214 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
- 3215 END
|
|
|
- 3216 ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
- 3217 OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
- 3218 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
- 3219 ELSIF SymTab.StrCompat(t, t2) THEN
|
|
|
- 3220 QbeGen.StrEq(op, q, q2, qt);
|
|
|
- 3221 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
- 3222 ELSIF SymTab.IsLongFamily(t)
|
|
|
- 3223 OR SymTab.IsLongFamily(t2) THEN
|
|
|
- 3224 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
- 3225 ELSE
|
|
|
- 3226 t := SymTab.BoolType();
|
|
|
- 3227 QbeGen.CopyOp("@", q)
|
|
|
- 3228 END
|
|
|
- 3229 ELSE SemError(213); t := SymTab.InvalidType;
|
|
|
- 3230 QbeGen.CopyOp("0", q)
|
|
|
- 3231 END;
|
|
|
- 3232 astCur := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB); .) ]
|
|
|
- 3233 (. IF NOT astMade THEN astCur := astA END; .)
|
|
|
- 3234 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
- 3235 Rel<VAR op: INTEGER>
|
|
|
- 3236 = "=" (. op := SymTab.OpEq; .)
|
|
|
- 3237 | "#" (. op := SymTab.OpNeq1; .)
|
|
|
- 3238 | "<" (. op := SymTab.OpLt; .)
|
|
|
- 3239 | "<=" (. op := SymTab.OpLe; .)
|
|
|
- 3240 | ">" (. op := SymTab.OpGt; .)
|
|
|
- 3241 | ">=" (. op := SymTab.OpGe; .)
|
|
|
- 3242 | "IN" (. op := SymTab.OpIn; .) .
|
|
|
- 3243 SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 3244 (. VAR t2, res2, lt, rt:
|
|
|
- 3245 SymTab.TypeIndex;
|
|
|
- 3246 op: INTEGER;
|
|
|
- 3247 q2, qt, wq, qf, q2a, q2b:
|
|
|
- 3248 QbeGen.QVal;
|
|
|
- 3249 neg, isR, isL, folded:
|
|
|
- 3250 BOOLEAN;
|
|
|
- 3251 fok: BOOLEAN;
|
|
|
- 3252 lw, rw, mw: CARDINAL;
|
|
|
- 3253 lTrue, lNext, lDone, qr, qs: QbeGen.QVal;
|
|
|
- 3254 astA, astB: AST.Node;
|
|
|
- 3255 astSign, astOp: INTEGER; .)
|
|
|
- 3256 = (. neg := FALSE; astSign := 0; .)
|
|
|
- 3257 [ "+" (. neg := TRUE; astSign := 1; .)
|
|
|
- 3258 | "-" (. neg := TRUE; astSign := -1; .) ]
|
|
|
- 3259 Term<t, q> (. astA := astCur;
|
|
|
- 3260 IF neg AND QbeGen.IsImm(q) THEN
|
|
|
- 3261 QbeGen.NegFold(q, q)
|
|
|
- 3262 END;
|
|
|
- 3263 IF astSign < 0 THEN
|
|
|
- 3264 astCur := AST.MakeUn(
|
|
|
- 3265 AST.NkUnary, AST.OpSub, astA);
|
|
|
- 3266 astA := astCur
|
|
|
- 3267 END; .)
|
|
|
- 3268 { AddOp<op>
|
|
|
- 3269 Term<t2, q2> (. astB := astCur; .)
|
|
|
- 3270 (. astOp := AST.OpAdd;
|
|
|
- 3271 IF op = SymTab.OpSub THEN astOp := AST.OpSub
|
|
|
- 3272 ELSIF op = SymTab.OpOr THEN astOp := AST.OpOr END;
|
|
|
- 3273 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
- 3274 astCur := astA;
|
|
|
- 3275 IF op = SymTab.OpOr THEN
|
|
|
- 3276 (* short-circuit: if q is true the RHS is skipped *)
|
|
|
- 3277 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
- 3278 t := SymTab.BoolType()
|
|
|
- 3279 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
- 3280 IF t # SymTab.InvalidType THEN
|
|
|
- 3281 QbeGen.CopyOp("@", q)
|
|
|
- 3282 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 3283 END
|
|
|
- 3284 ELSIF (op = SymTab.OpAdd)
|
|
|
- 3285 AND (SymTab.UStrCompat(t, t2)
|
|
|
- 3286 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
- 3287 AND (SymTab.ClassOf(t2) = SymTab.ClUStr))
|
|
|
- 3288 OR ((SymTab.ClassOf(t) = SymTab.ClUStr)
|
|
|
- 3289 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))
|
|
|
- 3290 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
- 3291 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))) THEN
|
|
|
- 3292 (* UString concatenation: a UCHAR operand becomes a
|
|
|
- 3293 1-codepoint UString; the result is a descriptor in the
|
|
|
- 3294 shim's concat buffer. Work on copies so neither
|
|
|
- 3295 operand is clobbered. *)
|
|
|
- 3296 t := SymTab.NewUStr();
|
|
|
- 3297 QbeGen.CopyOp("@", q)
|
|
|
- 3298 ELSIF (op = SymTab.OpAdd)
|
|
|
- 3299 AND (SymTab.StrCompat(t, t2)
|
|
|
- 3300 OR (SymTab.IsStrType(t)
|
|
|
- 3301 AND (SymTab.ClassOf(t2) = SymTab.ClChar))
|
|
|
- 3302 OR ((SymTab.ClassOf(t) = SymTab.ClChar)
|
|
|
- 3303 AND SymTab.IsStrType(t2))) THEN
|
|
|
- 3304 (* string concatenation; a CHAR operand becomes a
|
|
|
- 3305 1-character string literal. When both operands are
|
|
|
- 3306 constants, fold to a single string literal so a
|
|
|
- 3307 constructor element stays compile-time. *)
|
|
|
- 3308 QbeGen.StrFold(q, q2, SymTab.ClassOf(t), SymTab.ClassOf(t2),
|
|
|
- 3309 qt, fok);
|
|
|
- 3310 IF fok THEN QbeGen.CopyOp(qt, q)
|
|
|
- 3311 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 3312 END;
|
|
|
- 3313 t := SymTab.NewStr()
|
|
|
- 3314 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
- 3315 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
- 3316 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
- 3317 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
- 3318 mw := lw;
|
|
|
- 3319 IF rw > mw THEN mw := rw END;
|
|
|
- 3320 t := SymTab.NewSet(
|
|
|
- 3321 SymTab.NewSubR(0,
|
|
|
- 3322 VAL(INTEGER, mw) * 32 - 1));
|
|
|
- 3323 QbeGen.CopyOp("@", q)
|
|
|
- 3324 ELSE
|
|
|
- 3325 IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
|
|
|
- 3326 lt := t; rt := t2; t := res2
|
|
|
- 3327 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
- 3328 IF t # SymTab.InvalidType THEN
|
|
|
- 3329 isL := SymTab.IsLongFamily(t);
|
|
|
- 3330 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
- 3331 folded := FALSE;
|
|
|
- 3332 IF (NOT isL) AND (NOT isR)
|
|
|
- 3333 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
- 3334 IF op = SymTab.OpAdd THEN
|
|
|
- 3335 folded := QbeGen.Fold2(0, q, q2, qf)
|
|
|
- 3336 ELSE
|
|
|
- 3337 folded := QbeGen.Fold2(1, q, q2, qf)
|
|
|
- 3338 END
|
|
|
- 3339 END;
|
|
|
- 3340 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
- 3341 ELSE
|
|
|
- 3342 QbeGen.CopyOp("@", q)
|
|
|
- 3343 END
|
|
|
- 3344 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 3345 END
|
|
|
- 3346 END; .) }
|
|
|
- 3347 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
- 3348 AddOp<VAR op: INTEGER>
|
|
|
- 3349 = "+" (. op := SymTab.OpAdd; .)
|
|
|
- 3350 | "-" (. op := SymTab.OpSub; .)
|
|
|
- 3351 | "OR" (. op := SymTab.OpOr; .) .
|
|
|
- 3352 Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 3353 (. VAR t2, res2, lt, rt:
|
|
|
- 3354 SymTab.TypeIndex;
|
|
|
- 3355 op: INTEGER;
|
|
|
- 3356 q2, qt, wq, qf:
|
|
|
- 3357 QbeGen.QVal;
|
|
|
- 3358 isR, isL, folded: BOOLEAN;
|
|
|
- 3359 lw, rw, mw: CARDINAL;
|
|
|
- 3360 lNext, lFalse, lDone, qr, qs: QbeGen.QVal;
|
|
|
- 3361 astA, astB: AST.Node;
|
|
|
- 3362 astOp: INTEGER; .)
|
|
|
- 3363 = Fact<t, q> (. astA := astCur; .) { MulOp<op>
|
|
|
- 3364 Fact<t2, q2> (. astB := astCur; .)
|
|
|
- 3365 (. astOp := AST.OpMul;
|
|
|
- 3366 IF op = SymTab.OpSlash THEN astOp := AST.OpDiv
|
|
|
- 3367 ELSIF op = SymTab.OpDiv THEN astOp := AST.OpDiv
|
|
|
- 3368 ELSIF op = SymTab.OpMod THEN astOp := AST.OpMod
|
|
|
- 3369 ELSIF op = SymTab.OpAnd THEN astOp := AST.OpAnd END;
|
|
|
- 3370 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
- 3371 astCur := astA;
|
|
|
- 3372 IF op = SymTab.OpAnd THEN
|
|
|
- 3373 (* short-circuit: if q is false the RHS is skipped *)
|
|
|
- 3374 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
- 3375 t := SymTab.BoolType()
|
|
|
- 3376 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
- 3377 IF t # SymTab.InvalidType THEN QbeGen.CopyOp("@", q)
|
|
|
- 3378 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 3379 END
|
|
|
- 3380 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
- 3381 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
- 3382 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
- 3383 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
- 3384 mw := lw;
|
|
|
- 3385 IF rw > mw THEN mw := rw END;
|
|
|
- 3386 t := SymTab.NewSet(
|
|
|
- 3387 SymTab.NewSubR(0,
|
|
|
- 3388 VAL(INTEGER, mw) * 32 - 1));
|
|
|
- 3389 QbeGen.CopyOp("@", q)
|
|
|
- 3390 ELSE
|
|
|
- 3391 IF SymTab.ArithCheck(t, t2,
|
|
|
- 3392 (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
|
|
|
- 3393 res2) THEN
|
|
|
- 3394 lt := t; rt := t2; t := res2
|
|
|
- 3395 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
- 3396 IF t # SymTab.InvalidType THEN
|
|
|
- 3397 isL := SymTab.IsLongFamily(t);
|
|
|
- 3398 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
- 3399 folded := FALSE;
|
|
|
- 3400 IF (NOT isL) AND (NOT isR)
|
|
|
- 3401 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
- 3402 IF op = SymTab.OpTimes THEN
|
|
|
- 3403 folded := QbeGen.Fold2(2, q, q2, qf)
|
|
|
- 3404 ELSIF op = SymTab.OpDiv THEN
|
|
|
- 3405 folded := QbeGen.Fold2(3, q, q2, qf)
|
|
|
- 3406 ELSIF op = SymTab.OpMod THEN
|
|
|
- 3407 folded := QbeGen.Fold2(4, q, q2, qf)
|
|
|
- 3408 END
|
|
|
- 3409 END;
|
|
|
- 3410 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
- 3411 ELSE
|
|
|
- 3412 QbeGen.CopyOp("@", q)
|
|
|
- 3413 END
|
|
|
- 3414 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 3415 END
|
|
|
- 3416 END; .) }
|
|
|
- 3417 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
- 3418 MulOp<VAR op: INTEGER>
|
|
|
- 3419 = "*" (. op := SymTab.OpTimes; .)
|
|
|
- 3420 | "/" (. op := SymTab.OpSlash; .)
|
|
|
- 3421 | "DIV" (. op := SymTab.OpDiv; .)
|
|
|
- 3422 | "MOD" (. op := SymTab.OpMod; .)
|
|
|
- 3423 | ( "AND" | "&" ) (. op := SymTab.OpAnd; .) .
|
|
|
- 3424 Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 3425 (. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
|
- 3426 et, dt, t2, st, ct2, et2:
|
|
|
- 3427 SymTab.TypeIndex;
|
|
|
- 3428 dk: INTEGER;
|
|
|
- 3429 qd, q2, sq, qa, qm0, qr, qt:
|
|
|
- 3430 QbeGen.QVal;
|
|
|
- 3431 qn, vn: SymTab.Name;
|
|
|
- 3432 vt: SymTab.TypeIndex;
|
|
|
- 3433 c1, c2: INTEGER;
|
|
|
- 3434 lo, hi: INTEGER;
|
|
|
- 3435 isMax: BOOLEAN;
|
|
|
- 3436 called, isHigh, sfx, isCh,
|
|
|
- 3437 isU, uok, isStr: BOOLEAN;
|
|
|
- 3438 ucp: INTEGER; astIsLit: BOOLEAN;
|
|
|
- 3439 astD: AST.Node;
|
|
|
- 3440 astCall: BOOLEAN;
|
|
|
- 3441 astNode, astNot: AST.Node;
|
|
|
- 3442 j: CARDINAL;
|
|
|
- 3443 astArg2: AST.Node;
|
|
|
- 3444 astBrace: AST.Node;
|
|
|
- 3445 astRes: AST.Node; mname: SymTab.Name; isM: BOOLEAN;
|
|
|
- 3446 isConvF: BOOLEAN;
|
|
|
- 3447 fi, fj: CARDINAL; .)
|
|
|
- 3448 = (. astIsLit := FALSE; .)
|
|
|
- 3449 ( "__LINE__" (. QbeGen.IntStr(M2S.line, q);
|
|
|
- 3450 astIsLit := TRUE;
|
|
|
- 3451 astCur := AST.MakeLeaf(
|
|
|
- 3452 AST.NkIntLit, q);
|
|
|
- 3453 t := SymTab.IntType(); .)
|
|
|
- 3454 | "__FILE__" (. (* fold to the quoted file name *)
|
|
|
- 3455 s[0] := '"'; fi := 1; fj := 0;
|
|
|
- 3456 WHILE (M2S.fileName[fj] # CHR(0))
|
|
|
- 3457 AND (fi < HIGH(s)) DO
|
|
|
- 3458 s[fi] := M2S.fileName[fj];
|
|
|
- 3459 INC(fi); INC(fj)
|
|
|
- 3460 END;
|
|
|
- 3461 s[fi] := '"';
|
|
|
- 3462 s[fi + 1] := CHR(0);
|
|
|
+ 3147 ELSIF (SymTab.ClassOf(t) =
|
|
|
+ 3148 SymTab.ClClass)
|
|
|
+ 3149 AND SymTab.MethodExists(t, fname) THEN
|
|
|
+ 3150 (* a method on the call result:
|
|
|
+ 3151 a following ArgList makes
|
|
|
+ 3152 the call *)
|
|
|
+ 3153 mname := fname;
|
|
|
+ 3154 methCls := t; isM := TRUE;
|
|
|
+ 3155 t := SymTab.InvalidType
|
|
|
+ 3156 ELSIF NOT SymTab.FieldExists(t,
|
|
|
+ 3157 fname) THEN
|
|
|
+ 3158 SemError(216);
|
|
|
+ 3159 t := SymTab.InvalidType
|
|
|
+ 3160 ELSE
|
|
|
+ 3161 t := SymTab.FieldType(t, fname);
|
|
|
+ 3162 sfx := TRUE
|
|
|
+ 3163 END; .)
|
|
|
+ 3164 | "^" (. isM := FALSE;
|
|
|
+ 3165 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
+ 3166 astWrap := AST.MakeNode(
|
|
|
+ 3167 AST.NkDesignator);
|
|
|
+ 3168 AST.SetChild(astWrap, 0, node);
|
|
|
+ 3169 node := astWrap
|
|
|
+ 3170 END;
|
|
|
+ 3171 astSel := AST.MakeNode(AST.NkSelector);
|
|
|
+ 3172 AST.SetOp(astSel, AST.SelDeref);
|
|
|
+ 3173 AST.SetChild(node,
|
|
|
+ 3174 AST.NChild(node), astSel); IF t = SymTab.InvalidType THEN
|
|
|
+ 3175 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 3176 SymTab.ClPtr THEN
|
|
|
+ 3177 SemError(219);
|
|
|
+ 3178 t := SymTab.InvalidType
|
|
|
+ 3179 ELSE
|
|
|
+ 3180 bt := SymTab.PtrBase(t);
|
|
|
+ 3181 IF bt # SymTab.InvalidType THEN
|
|
|
+ 3182 t := bt; sfx := TRUE
|
|
|
+ 3183 END
|
|
|
+ 3184 END; .) .
|
|
|
+ 3185 Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3186 (. VAR t2: SymTab.TypeIndex;
|
|
|
+ 3187 op: INTEGER;
|
|
|
+ 3188 q2, qt, wl: QbeGen.QVal;
|
|
|
+ 3189 astA, astB: AST.Node;
|
|
|
+ 3190 astOp: INTEGER;
|
|
|
+ 3191 astMade: BOOLEAN;
|
|
|
+ 3192 isR: BOOLEAN; .)
|
|
|
+ 3193 = SimExpr<t, q> (. astA := astCur; astMade := FALSE; .)
|
|
|
+ 3194 [ Rel<op> SimExpr<t2, q2>
|
|
|
+ 3195 (. astB := astCur; astMade := TRUE;
|
|
|
+ 3196 astOp := AST.OpEq;
|
|
|
+ 3197 IF op = SymTab.OpNeq1 THEN astOp := AST.OpNe
|
|
|
+ 3198 ELSIF op = SymTab.OpNeq2 THEN astOp := AST.OpNe
|
|
|
+ 3199 ELSIF op = SymTab.OpLt THEN astOp := AST.OpLt
|
|
|
+ 3200 ELSIF op = SymTab.OpLe THEN astOp := AST.OpLe
|
|
|
+ 3201 ELSIF op = SymTab.OpGt THEN astOp := AST.OpGt
|
|
|
+ 3202 ELSIF op = SymTab.OpGe THEN astOp := AST.OpGe
|
|
|
+ 3203 ELSIF op = SymTab.OpIn THEN astOp := AST.OpIn
|
|
|
+ 3204 END;
|
|
|
+ 3205 IF op = SymTab.OpIn THEN
|
|
|
+ 3206 IF SymTab.InCheck(t, t2) THEN
|
|
|
+ 3207 IF (t = SymTab.InvalidType)
|
|
|
+ 3208 OR (t2 = SymTab.InvalidType) THEN
|
|
|
+ 3209 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
+ 3210 ELSE
|
|
|
+ 3211 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
+ 3212 END
|
|
|
+ 3213 ELSE SemError(222); t := SymTab.InvalidType;
|
|
|
+ 3214 QbeGen.CopyOp("0", q)
|
|
|
+ 3215 END
|
|
|
+ 3216 ELSIF SymTab.RelCheck(t, t2, op) THEN
|
|
|
+ 3217 IF (t = SymTab.InvalidType)
|
|
|
+ 3218 OR (t2 = SymTab.InvalidType) THEN
|
|
|
+ 3219 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
+ 3220 ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
|
|
|
+ 3221 OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
|
|
|
+ 3222 IF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
|
|
|
+ 3223 AND (op # SymTab.OpNeq2) THEN
|
|
|
+ 3224 SemError(213); t := SymTab.InvalidType;
|
|
|
+ 3225 QbeGen.CopyOp("0", q)
|
|
|
+ 3226 ELSE
|
|
|
+ 3227 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
+ 3228 END
|
|
|
+ 3229 ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 3230 OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 3231 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
+ 3232 ELSIF SymTab.StrCompat(t, t2) THEN
|
|
|
+ 3233 QbeGen.StrEq(op, q, q2, qt);
|
|
|
+ 3234 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
+ 3235 ELSIF SymTab.IsLongFamily(t)
|
|
|
+ 3236 OR SymTab.IsLongFamily(t2) THEN
|
|
|
+ 3237 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
+ 3238 ELSE
|
|
|
+ 3239 t := SymTab.BoolType();
|
|
|
+ 3240 QbeGen.CopyOp("@", q)
|
|
|
+ 3241 END
|
|
|
+ 3242 ELSE SemError(213); t := SymTab.InvalidType;
|
|
|
+ 3243 QbeGen.CopyOp("0", q)
|
|
|
+ 3244 END;
|
|
|
+ 3245 astCur := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB); .) ]
|
|
|
+ 3246 (. IF NOT astMade THEN astCur := astA END; .)
|
|
|
+ 3247 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
+ 3248 Rel<VAR op: INTEGER>
|
|
|
+ 3249 = "=" (. op := SymTab.OpEq; .)
|
|
|
+ 3250 | "#" (. op := SymTab.OpNeq1; .)
|
|
|
+ 3251 | "<" (. op := SymTab.OpLt; .)
|
|
|
+ 3252 | "<=" (. op := SymTab.OpLe; .)
|
|
|
+ 3253 | ">" (. op := SymTab.OpGt; .)
|
|
|
+ 3254 | ">=" (. op := SymTab.OpGe; .)
|
|
|
+ 3255 | "IN" (. op := SymTab.OpIn; .) .
|
|
|
+ 3256 SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3257 (. VAR t2, res2, lt, rt:
|
|
|
+ 3258 SymTab.TypeIndex;
|
|
|
+ 3259 op: INTEGER;
|
|
|
+ 3260 q2, qt, wq, qf, q2a, q2b:
|
|
|
+ 3261 QbeGen.QVal;
|
|
|
+ 3262 neg, isR, isL, folded:
|
|
|
+ 3263 BOOLEAN;
|
|
|
+ 3264 fok: BOOLEAN;
|
|
|
+ 3265 lw, rw, mw: CARDINAL;
|
|
|
+ 3266 lTrue, lNext, lDone, qr, qs: QbeGen.QVal;
|
|
|
+ 3267 astA, astB: AST.Node;
|
|
|
+ 3268 astSign, astOp: INTEGER; .)
|
|
|
+ 3269 = (. neg := FALSE; astSign := 0; .)
|
|
|
+ 3270 [ "+" (. neg := TRUE; astSign := 1; .)
|
|
|
+ 3271 | "-" (. neg := TRUE; astSign := -1; .) ]
|
|
|
+ 3272 Term<t, q> (. astA := astCur;
|
|
|
+ 3273 IF neg AND QbeGen.IsImm(q) THEN
|
|
|
+ 3274 QbeGen.NegFold(q, q)
|
|
|
+ 3275 END;
|
|
|
+ 3276 IF astSign < 0 THEN
|
|
|
+ 3277 astCur := AST.MakeUn(
|
|
|
+ 3278 AST.NkUnary, AST.OpSub, astA);
|
|
|
+ 3279 astA := astCur
|
|
|
+ 3280 END; .)
|
|
|
+ 3281 { AddOp<op>
|
|
|
+ 3282 Term<t2, q2> (. astB := astCur; .)
|
|
|
+ 3283 (. astOp := AST.OpAdd;
|
|
|
+ 3284 IF op = SymTab.OpSub THEN astOp := AST.OpSub
|
|
|
+ 3285 ELSIF op = SymTab.OpOr THEN astOp := AST.OpOr END;
|
|
|
+ 3286 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
+ 3287 astCur := astA;
|
|
|
+ 3288 IF op = SymTab.OpOr THEN
|
|
|
+ 3289 (* short-circuit: if q is true the RHS is skipped *)
|
|
|
+ 3290 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
+ 3291 t := SymTab.BoolType()
|
|
|
+ 3292 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
+ 3293 IF t # SymTab.InvalidType THEN
|
|
|
+ 3294 QbeGen.CopyOp("@", q)
|
|
|
+ 3295 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 3296 END
|
|
|
+ 3297 ELSIF (op = SymTab.OpAdd)
|
|
|
+ 3298 AND (SymTab.UStrCompat(t, t2)
|
|
|
+ 3299 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
+ 3300 AND (SymTab.ClassOf(t2) = SymTab.ClUStr))
|
|
|
+ 3301 OR ((SymTab.ClassOf(t) = SymTab.ClUStr)
|
|
|
+ 3302 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))
|
|
|
+ 3303 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
+ 3304 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))) THEN
|
|
|
+ 3305 (* UString concatenation: a UCHAR operand becomes a
|
|
|
+ 3306 1-codepoint UString; the result is a descriptor in the
|
|
|
+ 3307 shim's concat buffer. Work on copies so neither
|
|
|
+ 3308 operand is clobbered. *)
|
|
|
+ 3309 t := SymTab.NewUStr();
|
|
|
+ 3310 QbeGen.CopyOp("@", q)
|
|
|
+ 3311 ELSIF (op = SymTab.OpAdd)
|
|
|
+ 3312 AND (SymTab.StrCompat(t, t2)
|
|
|
+ 3313 OR (SymTab.IsStrType(t)
|
|
|
+ 3314 AND (SymTab.ClassOf(t2) = SymTab.ClChar))
|
|
|
+ 3315 OR ((SymTab.ClassOf(t) = SymTab.ClChar)
|
|
|
+ 3316 AND SymTab.IsStrType(t2))) THEN
|
|
|
+ 3317 (* string concatenation; a CHAR operand becomes a
|
|
|
+ 3318 1-character string literal. When both operands are
|
|
|
+ 3319 constants, fold to a single string literal so a
|
|
|
+ 3320 constructor element stays compile-time. *)
|
|
|
+ 3321 QbeGen.StrFold(q, q2, SymTab.ClassOf(t), SymTab.ClassOf(t2),
|
|
|
+ 3322 qt, fok);
|
|
|
+ 3323 IF fok THEN QbeGen.CopyOp(qt, q)
|
|
|
+ 3324 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 3325 END;
|
|
|
+ 3326 t := SymTab.NewStr()
|
|
|
+ 3327 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
+ 3328 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 3329 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 3330 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
+ 3331 mw := lw;
|
|
|
+ 3332 IF rw > mw THEN mw := rw END;
|
|
|
+ 3333 t := SymTab.NewSet(
|
|
|
+ 3334 SymTab.NewSubR(0,
|
|
|
+ 3335 VAL(INTEGER, mw) * 32 - 1));
|
|
|
+ 3336 QbeGen.CopyOp("@", q)
|
|
|
+ 3337 ELSE
|
|
|
+ 3338 IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
|
|
|
+ 3339 lt := t; rt := t2; t := res2
|
|
|
+ 3340 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
+ 3341 IF t # SymTab.InvalidType THEN
|
|
|
+ 3342 isL := SymTab.IsLongFamily(t);
|
|
|
+ 3343 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
+ 3344 folded := FALSE;
|
|
|
+ 3345 IF (NOT isL) AND (NOT isR)
|
|
|
+ 3346 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
+ 3347 IF op = SymTab.OpAdd THEN
|
|
|
+ 3348 folded := QbeGen.Fold2(0, q, q2, qf)
|
|
|
+ 3349 ELSE
|
|
|
+ 3350 folded := QbeGen.Fold2(1, q, q2, qf)
|
|
|
+ 3351 END
|
|
|
+ 3352 END;
|
|
|
+ 3353 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
+ 3354 ELSE
|
|
|
+ 3355 QbeGen.CopyOp("@", q)
|
|
|
+ 3356 END
|
|
|
+ 3357 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 3358 END
|
|
|
+ 3359 END; .) }
|
|
|
+ 3360 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
+ 3361 AddOp<VAR op: INTEGER>
|
|
|
+ 3362 = "+" (. op := SymTab.OpAdd; .)
|
|
|
+ 3363 | "-" (. op := SymTab.OpSub; .)
|
|
|
+ 3364 | "OR" (. op := SymTab.OpOr; .) .
|
|
|
+ 3365 Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3366 (. VAR t2, res2, lt, rt:
|
|
|
+ 3367 SymTab.TypeIndex;
|
|
|
+ 3368 op: INTEGER;
|
|
|
+ 3369 q2, qt, wq, qf:
|
|
|
+ 3370 QbeGen.QVal;
|
|
|
+ 3371 isR, isL, folded: BOOLEAN;
|
|
|
+ 3372 lw, rw, mw: CARDINAL;
|
|
|
+ 3373 lNext, lFalse, lDone, qr, qs: QbeGen.QVal;
|
|
|
+ 3374 astA, astB: AST.Node;
|
|
|
+ 3375 astOp: INTEGER; .)
|
|
|
+ 3376 = Fact<t, q> (. astA := astCur; .) { MulOp<op>
|
|
|
+ 3377 Fact<t2, q2> (. astB := astCur; .)
|
|
|
+ 3378 (. astOp := AST.OpMul;
|
|
|
+ 3379 IF op = SymTab.OpSlash THEN astOp := AST.OpDiv
|
|
|
+ 3380 ELSIF op = SymTab.OpDiv THEN astOp := AST.OpDiv
|
|
|
+ 3381 ELSIF op = SymTab.OpMod THEN astOp := AST.OpMod
|
|
|
+ 3382 ELSIF op = SymTab.OpAnd THEN astOp := AST.OpAnd END;
|
|
|
+ 3383 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
+ 3384 astCur := astA;
|
|
|
+ 3385 IF op = SymTab.OpAnd THEN
|
|
|
+ 3386 (* short-circuit: if q is false the RHS is skipped *)
|
|
|
+ 3387 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
+ 3388 t := SymTab.BoolType()
|
|
|
+ 3389 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
+ 3390 IF t # SymTab.InvalidType THEN QbeGen.CopyOp("@", q)
|
|
|
+ 3391 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 3392 END
|
|
|
+ 3393 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
+ 3394 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 3395 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 3396 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
+ 3397 mw := lw;
|
|
|
+ 3398 IF rw > mw THEN mw := rw END;
|
|
|
+ 3399 t := SymTab.NewSet(
|
|
|
+ 3400 SymTab.NewSubR(0,
|
|
|
+ 3401 VAL(INTEGER, mw) * 32 - 1));
|
|
|
+ 3402 QbeGen.CopyOp("@", q)
|
|
|
+ 3403 ELSE
|
|
|
+ 3404 IF SymTab.ArithCheck(t, t2,
|
|
|
+ 3405 (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
|
|
|
+ 3406 res2) THEN
|
|
|
+ 3407 lt := t; rt := t2; t := res2
|
|
|
+ 3408 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
+ 3409 IF t # SymTab.InvalidType THEN
|
|
|
+ 3410 isL := SymTab.IsLongFamily(t);
|
|
|
+ 3411 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
+ 3412 folded := FALSE;
|
|
|
+ 3413 IF (NOT isL) AND (NOT isR)
|
|
|
+ 3414 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
+ 3415 IF op = SymTab.OpTimes THEN
|
|
|
+ 3416 folded := QbeGen.Fold2(2, q, q2, qf)
|
|
|
+ 3417 ELSIF op = SymTab.OpDiv THEN
|
|
|
+ 3418 folded := QbeGen.Fold2(3, q, q2, qf)
|
|
|
+ 3419 ELSIF op = SymTab.OpMod THEN
|
|
|
+ 3420 folded := QbeGen.Fold2(4, q, q2, qf)
|
|
|
+ 3421 END
|
|
|
+ 3422 END;
|
|
|
+ 3423 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
+ 3424 ELSE
|
|
|
+ 3425 QbeGen.CopyOp("@", q)
|
|
|
+ 3426 END
|
|
|
+ 3427 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 3428 END
|
|
|
+ 3429 END; .) }
|
|
|
+ 3430 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
+ 3431 MulOp<VAR op: INTEGER>
|
|
|
+ 3432 = "*" (. op := SymTab.OpTimes; .)
|
|
|
+ 3433 | "/" (. op := SymTab.OpSlash; .)
|
|
|
+ 3434 | "DIV" (. op := SymTab.OpDiv; .)
|
|
|
+ 3435 | "MOD" (. op := SymTab.OpMod; .)
|
|
|
+ 3436 | ( "AND" | "&" ) (. op := SymTab.OpAnd; .) .
|
|
|
+ 3437 Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3438 (. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
|
+ 3439 et, dt, t2, st, ct2, et2:
|
|
|
+ 3440 SymTab.TypeIndex;
|
|
|
+ 3441 dk: INTEGER;
|
|
|
+ 3442 qd, q2, sq, qa, qm0, qr, qt:
|
|
|
+ 3443 QbeGen.QVal;
|
|
|
+ 3444 qn, vn: SymTab.Name;
|
|
|
+ 3445 vt: SymTab.TypeIndex;
|
|
|
+ 3446 c1, c2: INTEGER;
|
|
|
+ 3447 lo, hi: INTEGER;
|
|
|
+ 3448 isMax: BOOLEAN;
|
|
|
+ 3449 called, isHigh, sfx, isCh,
|
|
|
+ 3450 isU, uok, isStr: BOOLEAN;
|
|
|
+ 3451 ucp: INTEGER; astIsLit: BOOLEAN;
|
|
|
+ 3452 astD: AST.Node;
|
|
|
+ 3453 astCall: BOOLEAN;
|
|
|
+ 3454 astNode, astNot: AST.Node;
|
|
|
+ 3455 j: CARDINAL;
|
|
|
+ 3456 astArg2: AST.Node;
|
|
|
+ 3457 astBrace: AST.Node;
|
|
|
+ 3458 astRes: AST.Node; mname: SymTab.Name; isM: BOOLEAN;
|
|
|
+ 3459 isConvF: BOOLEAN;
|
|
|
+ 3460 fi, fj: CARDINAL; .)
|
|
|
+ 3461 = (. astIsLit := FALSE; .)
|
|
|
+ 3462 ( "__LINE__" (. QbeGen.IntStr(M2S.line, q);
|
|
|
3463 astIsLit := TRUE;
|
|
|
3464 astCur := AST.MakeLeaf(
|
|
|
- 3465 AST.NkStrLit, s);
|
|
|
- 3466 t := SymTab.NewStr();
|
|
|
- 3467 QbeGen.DeclStr(s, q); .)
|
|
|
- 3468 | integer (. LexString(s);
|
|
|
- 3469 QbeGen.NormInt(s, q); astIsLit := TRUE; astCur := AST.MakeLeaf(AST.NkIntLit, s);
|
|
|
- 3470 t := SymTab.IntType(); .)
|
|
|
- 3471 | charConst (. LexString(s);
|
|
|
- 3472 QbeGen.NormLit(s, q, isCh);
|
|
|
- 3473 astIsLit := TRUE;
|
|
|
- 3474 astCur := AST.MakeLeaf(
|
|
|
- 3475 AST.NkCharLit, s);
|
|
|
- 3476 t := SymTab.CharType(); .)
|
|
|
- 3477 | real (. LexString(s);
|
|
|
- 3478 QbeGen.NormReal(s, q);
|
|
|
- 3479 astIsLit := TRUE;
|
|
|
- 3480 astCur := AST.MakeLeaf(
|
|
|
- 3481 AST.NkRealLit, s);
|
|
|
- 3482 t := SymTab.RealType(); .)
|
|
|
- 3483 | string (. LexString(s);
|
|
|
- 3484 astIsLit := TRUE;
|
|
|
- 3485 astCur := AST.MakeLeaf(
|
|
|
- 3486 AST.NkStrLit, s);
|
|
|
- 3487 IF SymTab.StrLen(s) = 3 THEN
|
|
|
- 3488 t := SymTab.CharType();
|
|
|
- 3489 QbeGen.IntStr(
|
|
|
- 3490 QbeGen.CharVal(s), q)
|
|
|
- 3491 ELSIF SymTab.StrLen(s) = 2 THEN
|
|
|
- 3492 (* empty string: a string value
|
|
|
- 3493 for arrays, 0 for CHAR *)
|
|
|
- 3494 t := SymTab.NewEmptyStr();
|
|
|
- 3495 QbeGen.DeclStr(s, q)
|
|
|
- 3496 ELSE t := SymTab.NewStr();
|
|
|
- 3497 QbeGen.DeclStr(s, q);
|
|
|
- 3498 (* a literal's value IS its
|
|
|
- 3499 static descriptor address *)
|
|
|
- 3500 END; .)
|
|
|
- 3501 | ustring (. LexString(s);
|
|
|
- 3502 astIsLit := TRUE;
|
|
|
- 3503 astCur := AST.MakeLeaf(
|
|
|
- 3504 AST.NkStrLit, s);
|
|
|
- 3505 QbeGen.DeclUStr(s, q, isU, ucp,
|
|
|
- 3506 uok);
|
|
|
- 3507 IF NOT uok THEN
|
|
|
- 3508 SemError(234);
|
|
|
- 3509 t := SymTab.InvalidType
|
|
|
- 3510 ELSIF isU THEN
|
|
|
- 3511 t := SymTab.UCharType();
|
|
|
- 3512 QbeGen.IntStr(ucp, q)
|
|
|
- 3513 ELSE
|
|
|
- 3514 t := SymTab.NewUStr();
|
|
|
- 3515 END; .)
|
|
|
- 3516 | Design<dt, dk, qd, qn, sfx> (. astD := astCur; astCall := FALSE; astBrace := AST.NoNode;
|
|
|
- 3517 astNArgs := 0; called := FALSE;
|
|
|
- 3518 t := dt;
|
|
|
- 3519 IF dk = SymTab.KindConst THEN
|
|
|
- 3520 QbeGen.CopyOp(qd, q)
|
|
|
- 3521 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 3522 END; .)
|
|
|
- 3523 [ TypedBraceLit<dt, q> (. t := dt; astCall := TRUE;
|
|
|
- 3524 astBrace := astCur; .) ]
|
|
|
- 3525 [ ArgList<qn, dt, qd, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
- 3526 (. astCall := TRUE;
|
|
|
- 3527 IF (SymTab.SymKind(qn) = SymTab.KindType)
|
|
|
- 3528 OR (SymTab.SymKind(qn) = SymTab.KindPredef) THEN
|
|
|
- 3529 (* T(x): emit as the VAL builtin so Lower's
|
|
|
- 3530 conversion rules apply unchanged *)
|
|
|
- 3531 astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3532 AST.SetChild(astNode, 0,
|
|
|
- 3533 AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
- 3534 AST.SetChild(astNode, 1,
|
|
|
- 3535 AST.MakeLeaf(AST.NkIdent, qn));
|
|
|
- 3536 IF astNArgs = 1 THEN
|
|
|
- 3537 AST.SetChild(astNode, 2, astArgs[0])
|
|
|
- 3538 END;
|
|
|
- 3539 isConvF := TRUE
|
|
|
- 3540 ELSE astNode := AstCallNode(astD)
|
|
|
- 3541 END;
|
|
|
- 3542 astRes := astNode;
|
|
|
- 3543 t := ct2;
|
|
|
- 3544 QbeGen.CopyOp(q2, q);
|
|
|
- 3545 IF isConvF AND QbeGen.IsImm(convQ)
|
|
|
- 3546 AND OrdClass(convT) AND OrdClass(ct2) THEN
|
|
|
- 3547 QbeGen.CopyOp(convQ, q)
|
|
|
- 3548 END;
|
|
|
- 3549 sfx := FALSE; .)
|
|
|
- 3550 { ResultComp<t, q, sfx, astRes, mname, methCls, isM>
|
|
|
- 3551 [ (. astNArgs := 0; .)
|
|
|
- 3552 ArgList<mname, t, q, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
- 3553 (. astNode := AstCallNode(astRes);
|
|
|
- 3554 astRes := astNode;
|
|
|
- 3555 t := ct2;
|
|
|
- 3556 QbeGen.CopyOp(q2, q);
|
|
|
- 3557 sfx := FALSE; .) ] }
|
|
|
- 3558 (. IF sfx THEN
|
|
|
- 3559 IF t = SymTab.InvalidType THEN
|
|
|
- 3560 QbeGen.CopyOp("0", q)
|
|
|
- 3561 ELSIF (SymTab.ClassOf(t) #
|
|
|
- 3562 SymTab.ClRecord)
|
|
|
- 3563 AND (SymTab.ClassOf(t) # SymTab.ClSet)
|
|
|
- 3564 AND (SymTab.ClassOf(t) # SymTab.ClArray)
|
|
|
- 3565 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
- 3566 QbeGen.CopyOp("@", q)
|
|
|
- 3567 END
|
|
|
- 3568 END; .) ]
|
|
|
- 3569 (. IF called THEN
|
|
|
- 3570 astCur := astRes
|
|
|
- 3571 ELSIF astCall THEN
|
|
|
- 3572 astCur := astBrace
|
|
|
- 3573 ELSE astCur := astD
|
|
|
- 3574 END;
|
|
|
- 3575 astIsLit := TRUE;
|
|
|
- 3576 IF NOT called
|
|
|
- 3577 AND (dk = SymTab.KindProc) THEN
|
|
|
- 3578 (* bare zero-arg function
|
|
|
- 3579 call (parentheses may be
|
|
|
- 3580 omitted); a proper or
|
|
|
- 3581 parameterised proc here
|
|
|
- 3582 is 230 *)
|
|
|
- 3583 IF (SymTab.ProcNPar(qn) = 0)
|
|
|
- 3584 AND (SymTab.ProcRes(qn) # SymTab.InvalidType) THEN
|
|
|
- 3585 t := SymTab.ProcRes(qn);
|
|
|
- 3586 QbeGen.CopyOp("@", q);
|
|
|
- 3587 astCur := AST.MakeNode(AST.NkCall);
|
|
|
- 3588 AST.SetChild(astCur, 0, astD)
|
|
|
- 3589 ELSE
|
|
|
- 3590 t := SymTab.ProcTypeOf(qn);
|
|
|
- 3591 QbeGen.CopyOp("@", q)
|
|
|
- 3592 END
|
|
|
- 3593 END; .)
|
|
|
- 3594 | ( "HIGH" (. isHigh := TRUE; .)
|
|
|
- 3595 | ( "LEN" | "LENGTH" ) (. isHigh := FALSE; .) )
|
|
|
- 3596 "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE;
|
|
|
- 3597 isU := FALSE; .)
|
|
|
- 3598 | string (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
- 3599 isStr := TRUE;
|
|
|
- 3600 isU := FALSE;
|
|
|
- 3601 IF SymTab.StrLen(s) = 3 THEN
|
|
|
- 3602 dt := SymTab.CharType();
|
|
|
- 3603 QbeGen.IntStr(QbeGen.CharVal(s),
|
|
|
- 3604 qd)
|
|
|
- 3605 ELSE
|
|
|
- 3606 dt := SymTab.NewStr();
|
|
|
- 3607 QbeGen.DeclStr(s, qd);
|
|
|
- 3608 END;
|
|
|
- 3609 dk := -1;
|
|
|
- 3610 qn[0] := CHR(0); .)
|
|
|
- 3611 | ustring (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
- 3612 QbeGen.DeclUStr(s, qd, isU, ucp,
|
|
|
- 3613 uok);
|
|
|
- 3614 isStr := FALSE;
|
|
|
- 3615 IF NOT uok THEN
|
|
|
- 3616 SemError(234);
|
|
|
- 3617 dt := SymTab.InvalidType
|
|
|
- 3618 ELSIF isU THEN
|
|
|
- 3619 (* one codepoint: a UCHAR;
|
|
|
- 3620 LEN is 1, HIGH is 0 *)
|
|
|
- 3621 dt := SymTab.UCharType();
|
|
|
- 3622 QbeGen.IntStr(ucp, qd)
|
|
|
- 3623 ELSE
|
|
|
- 3624 dt := SymTab.NewUStr();
|
|
|
- 3625 END;
|
|
|
- 3626 dk := -1;
|
|
|
- 3627 qn[0] := CHR(0); .) )
|
|
|
- 3628 ")"
|
|
|
- 3629 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3630 IF isHigh THEN AST.SetChild(astNode, 0,
|
|
|
- 3631 AST.MakeLeaf(AST.NkIdent, "HIGH"))
|
|
|
- 3632 ELSE AST.SetChild(astNode, 0,
|
|
|
- 3633 AST.MakeLeaf(AST.NkIdent, "LEN")) END;
|
|
|
- 3634 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3635 astCur := astNode; astIsLit := TRUE;
|
|
|
- 3636 IF (dt # SymTab.InvalidType)
|
|
|
- 3637 AND (SymTab.ClassOf(dt) = SymTab.ClUStr) THEN
|
|
|
- 3638 (* UString: the count is
|
|
|
- 3639 the descriptor header *)
|
|
|
- 3640 t := SymTab.IntType();
|
|
|
- 3641 QbeGen.CopyOp("@", q)
|
|
|
- 3642 ELSIF (dt # SymTab.InvalidType)
|
|
|
- 3643 AND (SymTab.ClassOf(dt) = SymTab.ClUChar) THEN
|
|
|
- 3644 (* single UCHAR codepoint *)
|
|
|
- 3645 IF isHigh THEN
|
|
|
- 3646 QbeGen.CopyOp("0", qr)
|
|
|
- 3647 ELSE
|
|
|
- 3648 QbeGen.CopyOp("1", qr)
|
|
|
- 3649 END;
|
|
|
- 3650 t := SymTab.IntType();
|
|
|
- 3651 QbeGen.CopyOp(qr, q)
|
|
|
- 3652 ELSIF isStr THEN
|
|
|
- 3653 (* fold: content length at
|
|
|
- 3654 compile time *)
|
|
|
- 3655 IF SymTab.StrLen(s) = 3 THEN
|
|
|
- 3656 c1 := 1
|
|
|
- 3657 ELSE
|
|
|
- 3658 c1 :=
|
|
|
- 3659 SymTab.StrLen(s) - 2
|
|
|
- 3660 END;
|
|
|
- 3661 IF isHigh THEN
|
|
|
- 3662 DEC(c1)
|
|
|
- 3663 END;
|
|
|
- 3664 QbeGen.IntStr(c1, qr);
|
|
|
- 3665 t := SymTab.IntType();
|
|
|
- 3666 QbeGen.CopyOp(qr, q)
|
|
|
- 3667 ELSIF dt = SymTab.InvalidType THEN
|
|
|
- 3668 t := SymTab.InvalidType;
|
|
|
- 3669 QbeGen.CopyOp("0", q)
|
|
|
- 3670 ELSIF SymTab.ClassOf(dt) #
|
|
|
- 3671 SymTab.ClArray THEN
|
|
|
- 3672 SemError(217);
|
|
|
- 3673 t := SymTab.InvalidType;
|
|
|
- 3674 QbeGen.CopyOp("0", q)
|
|
|
- 3675 ELSE
|
|
|
- 3676 IF SymTab.IsOpenArray(dt) THEN
|
|
|
- 3677 t := SymTab.IntType();
|
|
|
- 3678 QbeGen.CopyOp("@", q)
|
|
|
- 3679 ELSE
|
|
|
- 3680 IF isHigh THEN
|
|
|
- 3681 QbeGen.IntStr(
|
|
|
- 3682 SymTab.ArrayHi(dt), qr)
|
|
|
- 3683 ELSE
|
|
|
- 3684 QbeGen.IntStr(VAL(
|
|
|
- 3685 INTEGER,
|
|
|
- 3686 SymTab.ArrayLen(dt)),
|
|
|
- 3687 qr)
|
|
|
- 3688 END;
|
|
|
- 3689 t := SymTab.IntType();
|
|
|
- 3690 QbeGen.CopyOp(qr, q)
|
|
|
- 3691 END
|
|
|
- 3692 END; .)
|
|
|
- 3693 | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
- 3694 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3695 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "SIZE"));
|
|
|
- 3696 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3697 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3698 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 3699 t := SymTab.InvalidType;
|
|
|
- 3700 QbeGen.CopyOp("0", q)
|
|
|
- 3701 ELSE
|
|
|
- 3702 QbeGen.IntStr(VAL(INTEGER,
|
|
|
- 3703 SymTab.ObjectSize(dt)), q);
|
|
|
- 3704 t := SymTab.IntType()
|
|
|
- 3705 END; .)
|
|
|
- 3706 | ( "SHIFT" (. isMax := FALSE; .)
|
|
|
- 3707 | "ROTATE" (. isMax := TRUE; .) )
|
|
|
- 3708 "(" Expr<et, q> (. astArg2 := astCur; .) "," Expr<et2, q2> ")"
|
|
|
- 3709 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3710 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
- 3711 AST.MakeLeaf(AST.NkIdent, "ROTATE"))
|
|
|
- 3712 ELSE AST.SetChild(astNode, 0,
|
|
|
- 3713 AST.MakeLeaf(AST.NkIdent, "SHIFT")) END;
|
|
|
- 3714 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
- 3715 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
- 3716 astCur := astNode; astIsLit := TRUE;
|
|
|
- 3717 (* set shift/rotate: isMax
|
|
|
- 3718 doubles as "rotate" *)
|
|
|
- 3719 IF (et # SymTab.InvalidType)
|
|
|
- 3720 AND (SymTab.ClassOf(et) =
|
|
|
- 3721 SymTab.ClSet) THEN
|
|
|
- 3722 t := et;
|
|
|
- 3723 QbeGen.CopyOp("@", q)
|
|
|
- 3724 ELSE SemError(230);
|
|
|
- 3725 t := SymTab.InvalidType;
|
|
|
- 3726 QbeGen.CopyOp("0", q)
|
|
|
- 3727 END; .)
|
|
|
- 3728 | ( "MIN" (. isMax := FALSE; .)
|
|
|
- 3729 | "MAX" (. isMax := TRUE; .) )
|
|
|
- 3730 "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
- 3731 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3732 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
- 3733 AST.MakeLeaf(AST.NkIdent, "MAX"))
|
|
|
- 3734 ELSE AST.SetChild(astNode, 0,
|
|
|
- 3735 AST.MakeLeaf(AST.NkIdent, "MIN")) END;
|
|
|
- 3736 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3737 astCur := astNode; astIsLit := TRUE;
|
|
|
- 3738 IF (dt # SymTab.InvalidType)
|
|
|
- 3739 AND (SymTab.ClassOf(dt) = SymTab.ClReal) THEN
|
|
|
- 3740 (* REAL/LONGREAL: the
|
|
|
- 3741 implementation bounds *)
|
|
|
- 3742 IF isMax THEN
|
|
|
- 3743 QbeGen.NormReal(
|
|
|
- 3744 "3.402823e38", q)
|
|
|
- 3745 ELSE QbeGen.NormReal(
|
|
|
- 3746 "-3.402823e38", q)
|
|
|
- 3747 END;
|
|
|
- 3748 t := SymTab.RealType()
|
|
|
- 3749 ELSIF (dt #
|
|
|
- 3750 SymTab.InvalidType)
|
|
|
- 3751 AND (SymTab.ClassOf(dt) =
|
|
|
- 3752 SymTab.ClLong) THEN
|
|
|
- 3753 IF isMax THEN
|
|
|
- 3754 QbeGen.CopyOp(
|
|
|
- 3755 "9223372036854775807", q)
|
|
|
- 3756 ELSE QbeGen.CopyOp(
|
|
|
- 3757 "-9223372036854775808", q)
|
|
|
- 3758 END;
|
|
|
- 3759 t := SymTab.LongType()
|
|
|
- 3760 ELSIF SymTab.TypeBounds(dt, lo,
|
|
|
- 3761 hi) THEN
|
|
|
- 3762 IF isMax THEN
|
|
|
- 3763 QbeGen.IntStr(hi, q)
|
|
|
- 3764 ELSE QbeGen.IntStr(lo, q)
|
|
|
- 3765 END;
|
|
|
- 3766 (* a set's bounds are those
|
|
|
- 3767 of its base type *)
|
|
|
- 3768 IF SymTab.ClassOf(dt) =
|
|
|
- 3769 SymTab.ClSet THEN
|
|
|
- 3770 t := SymTab.SetBase(dt)
|
|
|
- 3771 ELSE t := SymTab.IntType()
|
|
|
- 3772 END
|
|
|
- 3773 ELSE SemError(230);
|
|
|
- 3774 t := SymTab.InvalidType;
|
|
|
- 3775 QbeGen.CopyOp("0", q)
|
|
|
- 3776 END; .)
|
|
|
- 3777 | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
- 3778 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3779 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ADR"));
|
|
|
- 3780 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3781 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3782 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 3783 t := SymTab.InvalidType;
|
|
|
- 3784 QbeGen.CopyOp("0", q)
|
|
|
- 3785 ELSE
|
|
|
- 3786 IF sfx
|
|
|
- 3787 OR (dk = SymTab.KindVar)
|
|
|
- 3788 OR (dk = SymTab.KindParam) THEN
|
|
|
- 3789 QbeGen.CopyOp("@", q)
|
|
|
- 3790 ELSE SemError(230);
|
|
|
- 3791 QbeGen.CopyOp("0", q)
|
|
|
- 3792 END;
|
|
|
- 3793 t := SymTab.AddrType()
|
|
|
- 3794 END; .)
|
|
|
- 3795 | "CHR" "(" Expr<et, q> ")"
|
|
|
- 3796 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3797 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR"));
|
|
|
- 3798 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3799 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3800 (. IF (et # SymTab.InvalidType)
|
|
|
- 3801 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
- 3802 SemError(211) END;
|
|
|
- 3803 t := SymTab.CharType(); .)
|
|
|
- 3804 | "ORD" "(" Expr<et, q> ")"
|
|
|
- 3805 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3806 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ORD"));
|
|
|
- 3807 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3808 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3809 (. IF et # SymTab.InvalidType THEN
|
|
|
- 3810 IF (SymTab.ClassOf(et) #
|
|
|
- 3811 SymTab.ClChar)
|
|
|
- 3812 AND (SymTab.ClassOf(et) #
|
|
|
- 3813 SymTab.ClBool)
|
|
|
- 3814 AND (SymTab.ClassOf(et) #
|
|
|
- 3815 SymTab.ClEnum)
|
|
|
- 3816 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
- 3817 SemError(211) END
|
|
|
- 3818 END;
|
|
|
- 3819 t := SymTab.IntType(); .)
|
|
|
- 3820 | "CAP" "(" Expr<et, q> ")"
|
|
|
- 3821 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3822 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CAP"));
|
|
|
- 3823 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3824 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3825 (. IF QbeGen.IsImm(q)
|
|
|
- 3826 AND SymTab.ConstInt(q, lo) THEN
|
|
|
- 3827 IF (lo >= VAL(INTEGER, ORD("a"))) AND (lo <= VAL(INTEGER, ORD("z"))) THEN lo := lo - 32 END;
|
|
|
- 3828 QbeGen.IntStr(lo, q)
|
|
|
- 3829 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 3830 END;
|
|
|
- 3831 t := SymTab.CharType(); .)
|
|
|
- 3832 | "UCHR" "(" Expr<et, q> ")"
|
|
|
- 3833 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3834 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UCHR"));
|
|
|
- 3835 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3836 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3837 (. (* UCHR: the UCHAR constructor.
|
|
|
- 3838 CHAR -> UCHAR (identity);
|
|
|
- 3839 INTEGER familly -> UCHAR
|
|
|
- 3840 (codepoint value). *)
|
|
|
- 3841 IF (et # SymTab.InvalidType)
|
|
|
- 3842 AND (SymTab.ClassOf(et) # SymTab.ClChar)
|
|
|
- 3843 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
- 3844 SemError(211) END;
|
|
|
- 3845 t := SymTab.UCharType(); .)
|
|
|
- 3846 | "CHR8" "(" Expr<et, q> ")"
|
|
|
- 3847 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3848 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR8"));
|
|
|
- 3849 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3850 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3851 (. IF (et # SymTab.InvalidType)
|
|
|
- 3852 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
- 3853 SemError(211) END;
|
|
|
- 3854 t := SymTab.CharType(); .)
|
|
|
- 3855 | "UORD" "(" Expr<et, q> ")"
|
|
|
- 3856 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3857 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UORD"));
|
|
|
- 3858 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3859 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3860 (. (* UORD(u): the codepoint as a
|
|
|
- 3861 32-bit ordinal (INTEGER),
|
|
|
- 3862 cf. ORD for CHAR. *)
|
|
|
- 3863 IF (et # SymTab.InvalidType)
|
|
|
- 3864 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
- 3865 SemError(211) END;
|
|
|
- 3866 t := SymTab.IntType(); .)
|
|
|
- 3867 | "ABS" "(" Expr<et, q> ")"
|
|
|
- 3868 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3869 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ABS"));
|
|
|
- 3870 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3871 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3872 (. IF (et # SymTab.InvalidType)
|
|
|
- 3873 AND NOT SymTab.IsIntFamily(et)
|
|
|
- 3874 AND (SymTab.ClassOf(et) #
|
|
|
- 3875 SymTab.ClReal) THEN
|
|
|
- 3876 SemError(211)
|
|
|
- 3877 ELSIF QbeGen.IsImm(q)
|
|
|
- 3878 AND SymTab.ConstInt(q, lo) THEN
|
|
|
- 3879 IF lo < 0 THEN lo := -lo END;
|
|
|
- 3880 QbeGen.IntStr(lo, q)
|
|
|
- 3881 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 3882 END;
|
|
|
- 3883 t := et; .)
|
|
|
- 3884 | "ODD" "(" Expr<et, q> ")"
|
|
|
- 3885 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3886 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ODD"));
|
|
|
- 3887 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3888 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3889 (. IF (et # SymTab.InvalidType)
|
|
|
- 3890 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
- 3891 SemError(211) END;
|
|
|
- 3892 t := SymTab.BoolType();
|
|
|
- 3893 IF QbeGen.IsImm(q)
|
|
|
- 3894 AND SymTab.ConstInt(q, lo) THEN
|
|
|
- 3895 IF (lo MOD 2) # 0 THEN
|
|
|
- 3896 QbeGen.CopyOp("1", q)
|
|
|
- 3897 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 3898 END
|
|
|
- 3899 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 3900 END; .)
|
|
|
- 3901 | "TRUNC" "(" Expr<et, q> ")"
|
|
|
- 3902 (. (* TRUNC(x): real -> INTEGER, as the VAL builtin *)
|
|
|
- 3903 astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3904 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
- 3905 AST.SetChild(astNode, 1, AST.MakeLeaf(AST.NkIdent, "INTEGER"));
|
|
|
- 3906 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
- 3907 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3908 (. t := SymTab.IntType();
|
|
|
- 3909 QbeGen.CopyOp("@", q); .)
|
|
|
- 3910 | "FLOAT" "(" Expr<et, q> ")"
|
|
|
- 3911 (. (* FLOAT(i): integer -> REAL, as the VAL builtin *)
|
|
|
- 3912 astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3913 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
- 3914 AST.SetChild(astNode, 1, AST.MakeLeaf(AST.NkIdent, "REAL"));
|
|
|
- 3915 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
- 3916 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3917 (. t := SymTab.RealType();
|
|
|
- 3918 IF QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo) THEN QbeGen.NormReal(q, qa); QbeGen.CopyOp(qa, q)
|
|
|
- 3919 ELSE QbeGen.CopyOp("@", q) END; .)
|
|
|
- 3920 | ( "VAL" | "CONVERT" | "CAST" ) "(" GetIdent<vn> (. astArg2 := AST.MakeLeaf(AST.NkIdent, vn); .) "," Expr<et, q> ")"
|
|
|
- 3921 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3922 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
- 3923 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
- 3924 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
- 3925 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3926 (. IF NOT SymTab.Lookup(vn) THEN
|
|
|
- 3927 SemError(201);
|
|
|
- 3928 t := SymTab.InvalidType
|
|
|
- 3929 ELSE vt := SymTab.SymType(vn);
|
|
|
- 3930 IF vt = SymTab.InvalidType THEN
|
|
|
- 3931 t := SymTab.InvalidType
|
|
|
- 3932 ELSIF et =
|
|
|
- 3933 SymTab.InvalidType THEN
|
|
|
- 3934 t := vt
|
|
|
- 3935 ELSE
|
|
|
- 3936 c1 := SymTab.ClassOf(et);
|
|
|
- 3937 c2 := SymTab.ClassOf(vt);
|
|
|
- 3938 IF (c1 = SymTab.ClInt)
|
|
|
- 3939 AND (c2 = SymTab.ClLong) THEN
|
|
|
- 3940 IF NOT QbeGen.IsImm(q) THEN QbeGen.WidenLong(q, qa); QbeGen.CopyOp(qa, q) END;
|
|
|
- 3941 t := vt
|
|
|
- 3942 ELSIF (c1 = SymTab.ClLong)
|
|
|
- 3943 AND (c2 = SymTab.ClInt) THEN
|
|
|
- 3944 IF NOT (QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo)) THEN QbeGen.NarrowLong(q, qa); QbeGen.CopyOp(qa, q) END;
|
|
|
- 3945 t := vt
|
|
|
- 3946 ELSIF (c1 = SymTab.ClInt)
|
|
|
- 3947 AND (c2 = SymTab.ClReal) THEN
|
|
|
- 3948 IF QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo) THEN QbeGen.NormReal(q, qa) ELSE QbeGen.ConvIR(q, qa) END;
|
|
|
- 3949 QbeGen.CopyOp(qa, q);
|
|
|
- 3950 t := vt
|
|
|
- 3951 ELSIF (c1 = SymTab.ClLong)
|
|
|
- 3952 AND (c2 = SymTab.ClReal) THEN
|
|
|
- 3953 IF QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo) THEN QbeGen.NormReal(q, qa) ELSE QbeGen.ConvLR(q, qa) END;
|
|
|
- 3954 QbeGen.CopyOp(qa, q);
|
|
|
- 3955 t := vt
|
|
|
- 3956 ELSIF (c1 = SymTab.ClReal)
|
|
|
- 3957 AND (c2 = SymTab.ClInt) THEN
|
|
|
- 3958 QbeGen.ConvRI(q, qa);
|
|
|
- 3959 QbeGen.CopyOp(qa, q);
|
|
|
- 3960 t := vt
|
|
|
- 3961 ELSIF (c1 = SymTab.ClReal)
|
|
|
- 3962 AND (c2 = SymTab.ClLong) THEN
|
|
|
- 3963 QbeGen.ConvRL(q, qa);
|
|
|
- 3964 QbeGen.CopyOp(qa, q);
|
|
|
- 3965 t := vt
|
|
|
- 3966 ELSIF (c1 = SymTab.ClLong)
|
|
|
- 3967 AND (c2 = SymTab.ClLong) THEN
|
|
|
+ 3465 AST.NkIntLit, q);
|
|
|
+ 3466 t := SymTab.IntType(); .)
|
|
|
+ 3467 | "__FILE__" (. (* fold to the quoted file name *)
|
|
|
+ 3468 s[0] := '"'; fi := 1; fj := 0;
|
|
|
+ 3469 WHILE (M2S.fileName[fj] # CHR(0))
|
|
|
+ 3470 AND (fi < HIGH(s)) DO
|
|
|
+ 3471 s[fi] := M2S.fileName[fj];
|
|
|
+ 3472 INC(fi); INC(fj)
|
|
|
+ 3473 END;
|
|
|
+ 3474 s[fi] := '"';
|
|
|
+ 3475 s[fi + 1] := CHR(0);
|
|
|
+ 3476 astIsLit := TRUE;
|
|
|
+ 3477 astCur := AST.MakeLeaf(
|
|
|
+ 3478 AST.NkStrLit, s);
|
|
|
+ 3479 t := SymTab.NewStr();
|
|
|
+ 3480 QbeGen.DeclStr(s, q); .)
|
|
|
+ 3481 | integer (. LexString(s);
|
|
|
+ 3482 QbeGen.NormInt(s, q); astIsLit := TRUE; astCur := AST.MakeLeaf(AST.NkIntLit, s);
|
|
|
+ 3483 t := SymTab.IntType(); .)
|
|
|
+ 3484 | charConst (. LexString(s);
|
|
|
+ 3485 QbeGen.NormLit(s, q, isCh);
|
|
|
+ 3486 astIsLit := TRUE;
|
|
|
+ 3487 astCur := AST.MakeLeaf(
|
|
|
+ 3488 AST.NkCharLit, s);
|
|
|
+ 3489 t := SymTab.CharType(); .)
|
|
|
+ 3490 | real (. LexString(s);
|
|
|
+ 3491 QbeGen.NormReal(s, q);
|
|
|
+ 3492 astIsLit := TRUE;
|
|
|
+ 3493 astCur := AST.MakeLeaf(
|
|
|
+ 3494 AST.NkRealLit, s);
|
|
|
+ 3495 t := SymTab.RealType(); .)
|
|
|
+ 3496 | string (. LexString(s);
|
|
|
+ 3497 astIsLit := TRUE;
|
|
|
+ 3498 astCur := AST.MakeLeaf(
|
|
|
+ 3499 AST.NkStrLit, s);
|
|
|
+ 3500 IF SymTab.StrLen(s) = 3 THEN
|
|
|
+ 3501 t := SymTab.CharType();
|
|
|
+ 3502 QbeGen.IntStr(
|
|
|
+ 3503 QbeGen.CharVal(s), q)
|
|
|
+ 3504 ELSIF SymTab.StrLen(s) = 2 THEN
|
|
|
+ 3505 (* empty string: a string value
|
|
|
+ 3506 for arrays, 0 for CHAR *)
|
|
|
+ 3507 t := SymTab.NewEmptyStr();
|
|
|
+ 3508 QbeGen.DeclStr(s, q)
|
|
|
+ 3509 ELSE t := SymTab.NewStr();
|
|
|
+ 3510 QbeGen.DeclStr(s, q);
|
|
|
+ 3511 (* a literal's value IS its
|
|
|
+ 3512 static descriptor address *)
|
|
|
+ 3513 END; .)
|
|
|
+ 3514 | ustring (. LexString(s);
|
|
|
+ 3515 astIsLit := TRUE;
|
|
|
+ 3516 astCur := AST.MakeLeaf(
|
|
|
+ 3517 AST.NkStrLit, s);
|
|
|
+ 3518 QbeGen.DeclUStr(s, q, isU, ucp,
|
|
|
+ 3519 uok);
|
|
|
+ 3520 IF NOT uok THEN
|
|
|
+ 3521 SemError(234);
|
|
|
+ 3522 t := SymTab.InvalidType
|
|
|
+ 3523 ELSIF isU THEN
|
|
|
+ 3524 t := SymTab.UCharType();
|
|
|
+ 3525 QbeGen.IntStr(ucp, q)
|
|
|
+ 3526 ELSE
|
|
|
+ 3527 t := SymTab.NewUStr();
|
|
|
+ 3528 END; .)
|
|
|
+ 3529 | Design<dt, dk, qd, qn, sfx> (. astD := astCur; astCall := FALSE; astBrace := AST.NoNode;
|
|
|
+ 3530 astNArgs := 0; called := FALSE;
|
|
|
+ 3531 t := dt;
|
|
|
+ 3532 IF dk = SymTab.KindConst THEN
|
|
|
+ 3533 QbeGen.CopyOp(qd, q)
|
|
|
+ 3534 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 3535 END; .)
|
|
|
+ 3536 [ TypedBraceLit<dt, q> (. t := dt; astCall := TRUE;
|
|
|
+ 3537 astBrace := astCur; .) ]
|
|
|
+ 3538 [ ArgList<qn, dt, qd, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
+ 3539 (. astCall := TRUE;
|
|
|
+ 3540 IF (SymTab.SymKind(qn) = SymTab.KindType)
|
|
|
+ 3541 OR (SymTab.SymKind(qn) = SymTab.KindPredef) THEN
|
|
|
+ 3542 (* T(x): emit as the VAL builtin so Lower's
|
|
|
+ 3543 conversion rules apply unchanged *)
|
|
|
+ 3544 astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3545 AST.SetChild(astNode, 0,
|
|
|
+ 3546 AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
+ 3547 AST.SetChild(astNode, 1,
|
|
|
+ 3548 AST.MakeLeaf(AST.NkIdent, qn));
|
|
|
+ 3549 IF astNArgs = 1 THEN
|
|
|
+ 3550 AST.SetChild(astNode, 2, astArgs[0])
|
|
|
+ 3551 END;
|
|
|
+ 3552 isConvF := TRUE
|
|
|
+ 3553 ELSE astNode := AstCallNode(astD)
|
|
|
+ 3554 END;
|
|
|
+ 3555 astRes := astNode;
|
|
|
+ 3556 t := ct2;
|
|
|
+ 3557 QbeGen.CopyOp(q2, q);
|
|
|
+ 3558 IF isConvF AND QbeGen.IsImm(convQ)
|
|
|
+ 3559 AND OrdClass(convT) AND OrdClass(ct2) THEN
|
|
|
+ 3560 QbeGen.CopyOp(convQ, q)
|
|
|
+ 3561 END;
|
|
|
+ 3562 sfx := FALSE; .)
|
|
|
+ 3563 { ResultComp<t, q, sfx, astRes, mname, methCls, isM>
|
|
|
+ 3564 [ (. astNArgs := 0; .)
|
|
|
+ 3565 ArgList<mname, t, q, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
+ 3566 (. astNode := AstCallNode(astRes);
|
|
|
+ 3567 astRes := astNode;
|
|
|
+ 3568 t := ct2;
|
|
|
+ 3569 QbeGen.CopyOp(q2, q);
|
|
|
+ 3570 sfx := FALSE; .) ] }
|
|
|
+ 3571 (. IF sfx THEN
|
|
|
+ 3572 IF t = SymTab.InvalidType THEN
|
|
|
+ 3573 QbeGen.CopyOp("0", q)
|
|
|
+ 3574 ELSIF (SymTab.ClassOf(t) #
|
|
|
+ 3575 SymTab.ClRecord)
|
|
|
+ 3576 AND (SymTab.ClassOf(t) # SymTab.ClSet)
|
|
|
+ 3577 AND (SymTab.ClassOf(t) # SymTab.ClArray)
|
|
|
+ 3578 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
+ 3579 QbeGen.CopyOp("@", q)
|
|
|
+ 3580 END
|
|
|
+ 3581 END; .) ]
|
|
|
+ 3582 (. IF called THEN
|
|
|
+ 3583 astCur := astRes
|
|
|
+ 3584 ELSIF astCall THEN
|
|
|
+ 3585 astCur := astBrace
|
|
|
+ 3586 ELSE astCur := astD
|
|
|
+ 3587 END;
|
|
|
+ 3588 astIsLit := TRUE;
|
|
|
+ 3589 IF NOT called
|
|
|
+ 3590 AND (dk = SymTab.KindProc) THEN
|
|
|
+ 3591 (* bare zero-arg function
|
|
|
+ 3592 call (parentheses may be
|
|
|
+ 3593 omitted); a proper or
|
|
|
+ 3594 parameterised proc here
|
|
|
+ 3595 is 230 *)
|
|
|
+ 3596 IF (SymTab.ProcNPar(qn) = 0)
|
|
|
+ 3597 AND (SymTab.ProcRes(qn) # SymTab.InvalidType) THEN
|
|
|
+ 3598 t := SymTab.ProcRes(qn);
|
|
|
+ 3599 QbeGen.CopyOp("@", q);
|
|
|
+ 3600 astCur := AST.MakeNode(AST.NkCall);
|
|
|
+ 3601 AST.SetChild(astCur, 0, astD)
|
|
|
+ 3602 ELSE
|
|
|
+ 3603 t := SymTab.ProcTypeOf(qn);
|
|
|
+ 3604 QbeGen.CopyOp("@", q)
|
|
|
+ 3605 END
|
|
|
+ 3606 END; .)
|
|
|
+ 3607 | ( "HIGH" (. isHigh := TRUE; .)
|
|
|
+ 3608 | ( "LEN" | "LENGTH" ) (. isHigh := FALSE; .) )
|
|
|
+ 3609 "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE;
|
|
|
+ 3610 isU := FALSE; .)
|
|
|
+ 3611 | string (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
+ 3612 isStr := TRUE;
|
|
|
+ 3613 isU := FALSE;
|
|
|
+ 3614 IF SymTab.StrLen(s) = 3 THEN
|
|
|
+ 3615 dt := SymTab.CharType();
|
|
|
+ 3616 QbeGen.IntStr(QbeGen.CharVal(s),
|
|
|
+ 3617 qd)
|
|
|
+ 3618 ELSE
|
|
|
+ 3619 dt := SymTab.NewStr();
|
|
|
+ 3620 QbeGen.DeclStr(s, qd);
|
|
|
+ 3621 END;
|
|
|
+ 3622 dk := -1;
|
|
|
+ 3623 qn[0] := CHR(0); .)
|
|
|
+ 3624 | ustring (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
+ 3625 QbeGen.DeclUStr(s, qd, isU, ucp,
|
|
|
+ 3626 uok);
|
|
|
+ 3627 isStr := FALSE;
|
|
|
+ 3628 IF NOT uok THEN
|
|
|
+ 3629 SemError(234);
|
|
|
+ 3630 dt := SymTab.InvalidType
|
|
|
+ 3631 ELSIF isU THEN
|
|
|
+ 3632 (* one codepoint: a UCHAR;
|
|
|
+ 3633 LEN is 1, HIGH is 0 *)
|
|
|
+ 3634 dt := SymTab.UCharType();
|
|
|
+ 3635 QbeGen.IntStr(ucp, qd)
|
|
|
+ 3636 ELSE
|
|
|
+ 3637 dt := SymTab.NewUStr();
|
|
|
+ 3638 END;
|
|
|
+ 3639 dk := -1;
|
|
|
+ 3640 qn[0] := CHR(0); .) )
|
|
|
+ 3641 ")"
|
|
|
+ 3642 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3643 IF isHigh THEN AST.SetChild(astNode, 0,
|
|
|
+ 3644 AST.MakeLeaf(AST.NkIdent, "HIGH"))
|
|
|
+ 3645 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 3646 AST.MakeLeaf(AST.NkIdent, "LEN")) END;
|
|
|
+ 3647 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3648 astCur := astNode; astIsLit := TRUE;
|
|
|
+ 3649 IF (dt # SymTab.InvalidType)
|
|
|
+ 3650 AND (SymTab.ClassOf(dt) = SymTab.ClUStr) THEN
|
|
|
+ 3651 (* UString: the count is
|
|
|
+ 3652 the descriptor header *)
|
|
|
+ 3653 t := SymTab.IntType();
|
|
|
+ 3654 QbeGen.CopyOp("@", q)
|
|
|
+ 3655 ELSIF (dt # SymTab.InvalidType)
|
|
|
+ 3656 AND (SymTab.ClassOf(dt) = SymTab.ClUChar) THEN
|
|
|
+ 3657 (* single UCHAR codepoint *)
|
|
|
+ 3658 IF isHigh THEN
|
|
|
+ 3659 QbeGen.CopyOp("0", qr)
|
|
|
+ 3660 ELSE
|
|
|
+ 3661 QbeGen.CopyOp("1", qr)
|
|
|
+ 3662 END;
|
|
|
+ 3663 t := SymTab.IntType();
|
|
|
+ 3664 QbeGen.CopyOp(qr, q)
|
|
|
+ 3665 ELSIF isStr THEN
|
|
|
+ 3666 (* fold: content length at
|
|
|
+ 3667 compile time *)
|
|
|
+ 3668 IF SymTab.StrLen(s) = 3 THEN
|
|
|
+ 3669 c1 := 1
|
|
|
+ 3670 ELSE
|
|
|
+ 3671 c1 :=
|
|
|
+ 3672 SymTab.StrLen(s) - 2
|
|
|
+ 3673 END;
|
|
|
+ 3674 IF isHigh THEN
|
|
|
+ 3675 DEC(c1)
|
|
|
+ 3676 END;
|
|
|
+ 3677 QbeGen.IntStr(c1, qr);
|
|
|
+ 3678 t := SymTab.IntType();
|
|
|
+ 3679 QbeGen.CopyOp(qr, q)
|
|
|
+ 3680 ELSIF dt = SymTab.InvalidType THEN
|
|
|
+ 3681 t := SymTab.InvalidType;
|
|
|
+ 3682 QbeGen.CopyOp("0", q)
|
|
|
+ 3683 ELSIF SymTab.ClassOf(dt) #
|
|
|
+ 3684 SymTab.ClArray THEN
|
|
|
+ 3685 SemError(217);
|
|
|
+ 3686 t := SymTab.InvalidType;
|
|
|
+ 3687 QbeGen.CopyOp("0", q)
|
|
|
+ 3688 ELSE
|
|
|
+ 3689 IF SymTab.IsOpenArray(dt) THEN
|
|
|
+ 3690 t := SymTab.IntType();
|
|
|
+ 3691 QbeGen.CopyOp("@", q)
|
|
|
+ 3692 ELSE
|
|
|
+ 3693 IF isHigh THEN
|
|
|
+ 3694 QbeGen.IntStr(
|
|
|
+ 3695 SymTab.ArrayHi(dt), qr)
|
|
|
+ 3696 ELSE
|
|
|
+ 3697 QbeGen.IntStr(VAL(
|
|
|
+ 3698 INTEGER,
|
|
|
+ 3699 SymTab.ArrayLen(dt)),
|
|
|
+ 3700 qr)
|
|
|
+ 3701 END;
|
|
|
+ 3702 t := SymTab.IntType();
|
|
|
+ 3703 QbeGen.CopyOp(qr, q)
|
|
|
+ 3704 END
|
|
|
+ 3705 END; .)
|
|
|
+ 3706 | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
+ 3707 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3708 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "SIZE"));
|
|
|
+ 3709 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3710 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3711 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 3712 t := SymTab.InvalidType;
|
|
|
+ 3713 QbeGen.CopyOp("0", q)
|
|
|
+ 3714 ELSE
|
|
|
+ 3715 QbeGen.IntStr(VAL(INTEGER,
|
|
|
+ 3716 SymTab.ObjectSize(dt)), q);
|
|
|
+ 3717 t := SymTab.IntType()
|
|
|
+ 3718 END; .)
|
|
|
+ 3719 | ( "SHIFT" (. isMax := FALSE; .)
|
|
|
+ 3720 | "ROTATE" (. isMax := TRUE; .) )
|
|
|
+ 3721 "(" Expr<et, q> (. astArg2 := astCur; .) "," Expr<et2, q2> ")"
|
|
|
+ 3722 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3723 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
+ 3724 AST.MakeLeaf(AST.NkIdent, "ROTATE"))
|
|
|
+ 3725 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 3726 AST.MakeLeaf(AST.NkIdent, "SHIFT")) END;
|
|
|
+ 3727 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
+ 3728 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 3729 astCur := astNode; astIsLit := TRUE;
|
|
|
+ 3730 (* set shift/rotate: isMax
|
|
|
+ 3731 doubles as "rotate" *)
|
|
|
+ 3732 IF (et # SymTab.InvalidType)
|
|
|
+ 3733 AND (SymTab.ClassOf(et) =
|
|
|
+ 3734 SymTab.ClSet) THEN
|
|
|
+ 3735 t := et;
|
|
|
+ 3736 QbeGen.CopyOp("@", q)
|
|
|
+ 3737 ELSE SemError(230);
|
|
|
+ 3738 t := SymTab.InvalidType;
|
|
|
+ 3739 QbeGen.CopyOp("0", q)
|
|
|
+ 3740 END; .)
|
|
|
+ 3741 | ( "MIN" (. isMax := FALSE; .)
|
|
|
+ 3742 | "MAX" (. isMax := TRUE; .) )
|
|
|
+ 3743 "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
+ 3744 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3745 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
+ 3746 AST.MakeLeaf(AST.NkIdent, "MAX"))
|
|
|
+ 3747 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 3748 AST.MakeLeaf(AST.NkIdent, "MIN")) END;
|
|
|
+ 3749 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3750 astCur := astNode; astIsLit := TRUE;
|
|
|
+ 3751 IF (dt # SymTab.InvalidType)
|
|
|
+ 3752 AND (SymTab.ClassOf(dt) = SymTab.ClReal) THEN
|
|
|
+ 3753 (* REAL/LONGREAL: the
|
|
|
+ 3754 implementation bounds *)
|
|
|
+ 3755 IF isMax THEN
|
|
|
+ 3756 QbeGen.NormReal(
|
|
|
+ 3757 "3.402823e38", q)
|
|
|
+ 3758 ELSE QbeGen.NormReal(
|
|
|
+ 3759 "-3.402823e38", q)
|
|
|
+ 3760 END;
|
|
|
+ 3761 t := SymTab.RealType()
|
|
|
+ 3762 ELSIF (dt #
|
|
|
+ 3763 SymTab.InvalidType)
|
|
|
+ 3764 AND (SymTab.ClassOf(dt) =
|
|
|
+ 3765 SymTab.ClLong) THEN
|
|
|
+ 3766 IF isMax THEN
|
|
|
+ 3767 QbeGen.CopyOp(
|
|
|
+ 3768 "9223372036854775807", q)
|
|
|
+ 3769 ELSE QbeGen.CopyOp(
|
|
|
+ 3770 "-9223372036854775808", q)
|
|
|
+ 3771 END;
|
|
|
+ 3772 t := SymTab.LongType()
|
|
|
+ 3773 ELSIF SymTab.TypeBounds(dt, lo,
|
|
|
+ 3774 hi) THEN
|
|
|
+ 3775 IF isMax THEN
|
|
|
+ 3776 QbeGen.IntStr(hi, q)
|
|
|
+ 3777 ELSE QbeGen.IntStr(lo, q)
|
|
|
+ 3778 END;
|
|
|
+ 3779 (* a set's bounds are those
|
|
|
+ 3780 of its base type *)
|
|
|
+ 3781 IF SymTab.ClassOf(dt) =
|
|
|
+ 3782 SymTab.ClSet THEN
|
|
|
+ 3783 t := SymTab.SetBase(dt)
|
|
|
+ 3784 ELSE t := SymTab.IntType()
|
|
|
+ 3785 END
|
|
|
+ 3786 ELSE SemError(230);
|
|
|
+ 3787 t := SymTab.InvalidType;
|
|
|
+ 3788 QbeGen.CopyOp("0", q)
|
|
|
+ 3789 END; .)
|
|
|
+ 3790 | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
+ 3791 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3792 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ADR"));
|
|
|
+ 3793 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3794 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3795 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 3796 t := SymTab.InvalidType;
|
|
|
+ 3797 QbeGen.CopyOp("0", q)
|
|
|
+ 3798 ELSE
|
|
|
+ 3799 IF sfx
|
|
|
+ 3800 OR (dk = SymTab.KindVar)
|
|
|
+ 3801 OR (dk = SymTab.KindParam) THEN
|
|
|
+ 3802 QbeGen.CopyOp("@", q)
|
|
|
+ 3803 ELSE SemError(230);
|
|
|
+ 3804 QbeGen.CopyOp("0", q)
|
|
|
+ 3805 END;
|
|
|
+ 3806 t := SymTab.AddrType()
|
|
|
+ 3807 END; .)
|
|
|
+ 3808 | "CHR" "(" Expr<et, q> ")"
|
|
|
+ 3809 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3810 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR"));
|
|
|
+ 3811 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3812 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3813 (. IF (et # SymTab.InvalidType)
|
|
|
+ 3814 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
+ 3815 SemError(211) END;
|
|
|
+ 3816 t := SymTab.CharType(); .)
|
|
|
+ 3817 | "ORD" "(" Expr<et, q> ")"
|
|
|
+ 3818 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3819 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ORD"));
|
|
|
+ 3820 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3821 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3822 (. IF et # SymTab.InvalidType THEN
|
|
|
+ 3823 IF (SymTab.ClassOf(et) #
|
|
|
+ 3824 SymTab.ClChar)
|
|
|
+ 3825 AND (SymTab.ClassOf(et) #
|
|
|
+ 3826 SymTab.ClBool)
|
|
|
+ 3827 AND (SymTab.ClassOf(et) #
|
|
|
+ 3828 SymTab.ClEnum)
|
|
|
+ 3829 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
+ 3830 SemError(211) END
|
|
|
+ 3831 END;
|
|
|
+ 3832 t := SymTab.IntType(); .)
|
|
|
+ 3833 | "CAP" "(" Expr<et, q> ")"
|
|
|
+ 3834 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3835 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CAP"));
|
|
|
+ 3836 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3837 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3838 (. IF QbeGen.IsImm(q)
|
|
|
+ 3839 AND SymTab.ConstInt(q, lo) THEN
|
|
|
+ 3840 IF (lo >= VAL(INTEGER, ORD("a"))) AND (lo <= VAL(INTEGER, ORD("z"))) THEN lo := lo - 32 END;
|
|
|
+ 3841 QbeGen.IntStr(lo, q)
|
|
|
+ 3842 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 3843 END;
|
|
|
+ 3844 t := SymTab.CharType(); .)
|
|
|
+ 3845 | "UCHR" "(" Expr<et, q> ")"
|
|
|
+ 3846 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3847 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UCHR"));
|
|
|
+ 3848 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3849 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3850 (. (* UCHR: the UCHAR constructor.
|
|
|
+ 3851 CHAR -> UCHAR (identity);
|
|
|
+ 3852 INTEGER familly -> UCHAR
|
|
|
+ 3853 (codepoint value). *)
|
|
|
+ 3854 IF (et # SymTab.InvalidType)
|
|
|
+ 3855 AND (SymTab.ClassOf(et) # SymTab.ClChar)
|
|
|
+ 3856 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
+ 3857 SemError(211) END;
|
|
|
+ 3858 t := SymTab.UCharType(); .)
|
|
|
+ 3859 | "CHR8" "(" Expr<et, q> ")"
|
|
|
+ 3860 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3861 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR8"));
|
|
|
+ 3862 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3863 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3864 (. IF (et # SymTab.InvalidType)
|
|
|
+ 3865 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
+ 3866 SemError(211) END;
|
|
|
+ 3867 t := SymTab.CharType(); .)
|
|
|
+ 3868 | "UORD" "(" Expr<et, q> ")"
|
|
|
+ 3869 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3870 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UORD"));
|
|
|
+ 3871 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3872 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3873 (. (* UORD(u): the codepoint as a
|
|
|
+ 3874 32-bit ordinal (INTEGER),
|
|
|
+ 3875 cf. ORD for CHAR. *)
|
|
|
+ 3876 IF (et # SymTab.InvalidType)
|
|
|
+ 3877 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
+ 3878 SemError(211) END;
|
|
|
+ 3879 t := SymTab.IntType(); .)
|
|
|
+ 3880 | "ABS" "(" Expr<et, q> ")"
|
|
|
+ 3881 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3882 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ABS"));
|
|
|
+ 3883 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3884 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3885 (. IF (et # SymTab.InvalidType)
|
|
|
+ 3886 AND NOT SymTab.IsIntFamily(et)
|
|
|
+ 3887 AND (SymTab.ClassOf(et) #
|
|
|
+ 3888 SymTab.ClReal) THEN
|
|
|
+ 3889 SemError(211)
|
|
|
+ 3890 ELSIF QbeGen.IsImm(q)
|
|
|
+ 3891 AND SymTab.ConstInt(q, lo) THEN
|
|
|
+ 3892 IF lo < 0 THEN lo := -lo END;
|
|
|
+ 3893 QbeGen.IntStr(lo, q)
|
|
|
+ 3894 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 3895 END;
|
|
|
+ 3896 t := et; .)
|
|
|
+ 3897 | "ODD" "(" Expr<et, q> ")"
|
|
|
+ 3898 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3899 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ODD"));
|
|
|
+ 3900 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3901 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3902 (. IF (et # SymTab.InvalidType)
|
|
|
+ 3903 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
+ 3904 SemError(211) END;
|
|
|
+ 3905 t := SymTab.BoolType();
|
|
|
+ 3906 IF QbeGen.IsImm(q)
|
|
|
+ 3907 AND SymTab.ConstInt(q, lo) THEN
|
|
|
+ 3908 IF (lo MOD 2) # 0 THEN
|
|
|
+ 3909 QbeGen.CopyOp("1", q)
|
|
|
+ 3910 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 3911 END
|
|
|
+ 3912 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 3913 END; .)
|
|
|
+ 3914 | "TRUNC" "(" Expr<et, q> ")"
|
|
|
+ 3915 (. (* TRUNC(x): real -> INTEGER, as the VAL builtin *)
|
|
|
+ 3916 astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3917 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
+ 3918 AST.SetChild(astNode, 1, AST.MakeLeaf(AST.NkIdent, "INTEGER"));
|
|
|
+ 3919 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 3920 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3921 (. t := SymTab.IntType();
|
|
|
+ 3922 QbeGen.CopyOp("@", q); .)
|
|
|
+ 3923 | "FLOAT" "(" Expr<et, q> ")"
|
|
|
+ 3924 (. (* FLOAT(i): integer -> REAL, as the VAL builtin *)
|
|
|
+ 3925 astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3926 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
+ 3927 AST.SetChild(astNode, 1, AST.MakeLeaf(AST.NkIdent, "REAL"));
|
|
|
+ 3928 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 3929 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3930 (. t := SymTab.RealType();
|
|
|
+ 3931 IF QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo) THEN QbeGen.NormReal(q, qa); QbeGen.CopyOp(qa, q)
|
|
|
+ 3932 ELSE QbeGen.CopyOp("@", q) END; .)
|
|
|
+ 3933 | ( "VAL" | "CONVERT" | "CAST" ) "(" GetIdent<vn> (. astArg2 := AST.MakeLeaf(AST.NkIdent, vn); .) "," Expr<et, q> ")"
|
|
|
+ 3934 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3935 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
+ 3936 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
+ 3937 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 3938 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3939 (. IF NOT SymTab.Lookup(vn) THEN
|
|
|
+ 3940 SemError(201);
|
|
|
+ 3941 t := SymTab.InvalidType
|
|
|
+ 3942 ELSE vt := SymTab.SymType(vn);
|
|
|
+ 3943 IF vt = SymTab.InvalidType THEN
|
|
|
+ 3944 t := SymTab.InvalidType
|
|
|
+ 3945 ELSIF et =
|
|
|
+ 3946 SymTab.InvalidType THEN
|
|
|
+ 3947 t := vt
|
|
|
+ 3948 ELSE
|
|
|
+ 3949 c1 := SymTab.ClassOf(et);
|
|
|
+ 3950 c2 := SymTab.ClassOf(vt);
|
|
|
+ 3951 IF (c1 = SymTab.ClInt)
|
|
|
+ 3952 AND (c2 = SymTab.ClLong) THEN
|
|
|
+ 3953 IF NOT QbeGen.IsImm(q) THEN QbeGen.WidenLong(q, qa); QbeGen.CopyOp(qa, q) END;
|
|
|
+ 3954 t := vt
|
|
|
+ 3955 ELSIF (c1 = SymTab.ClLong)
|
|
|
+ 3956 AND (c2 = SymTab.ClInt) THEN
|
|
|
+ 3957 IF NOT (QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo)) THEN QbeGen.NarrowLong(q, qa); QbeGen.CopyOp(qa, q) END;
|
|
|
+ 3958 t := vt
|
|
|
+ 3959 ELSIF (c1 = SymTab.ClInt)
|
|
|
+ 3960 AND (c2 = SymTab.ClReal) THEN
|
|
|
+ 3961 IF QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo) THEN QbeGen.NormReal(q, qa) ELSE QbeGen.ConvIR(q, qa) END;
|
|
|
+ 3962 QbeGen.CopyOp(qa, q);
|
|
|
+ 3963 t := vt
|
|
|
+ 3964 ELSIF (c1 = SymTab.ClLong)
|
|
|
+ 3965 AND (c2 = SymTab.ClReal) THEN
|
|
|
+ 3966 IF QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo) THEN QbeGen.NormReal(q, qa) ELSE QbeGen.ConvLR(q, qa) END;
|
|
|
+ 3967 QbeGen.CopyOp(qa, q);
|
|
|
3968 t := vt
|
|
|
- 3969 ELSIF ((c1 = SymTab.ClInt)
|
|
|
- 3970 OR (c1 =
|
|
|
- 3971 SymTab.ClChar)
|
|
|
- 3972 OR (c1 =
|
|
|
- 3973 SymTab.ClBool)
|
|
|
- 3974 OR (c1 =
|
|
|
- 3975 SymTab.ClEnum))
|
|
|
- 3976 AND ((c2 = SymTab.ClInt)
|
|
|
- 3977 OR (c2 =
|
|
|
- 3978 SymTab.ClChar)
|
|
|
- 3979 OR (c2 =
|
|
|
- 3980 SymTab.ClBool)
|
|
|
- 3981 OR (c2 =
|
|
|
- 3982 SymTab.ClEnum)) THEN
|
|
|
- 3983 t := vt
|
|
|
- 3984 ELSIF (c1 = SymTab.ClPtr)
|
|
|
- 3985 AND (c2 = SymTab.ClPtr) THEN
|
|
|
- 3986 t := vt
|
|
|
- 3987 ELSIF ((c1 = SymTab.ClProc)
|
|
|
- 3988 AND (c2 = SymTab.ClProc))
|
|
|
- 3989 OR ((c1 = SymTab.ClProc) AND (c2 = SymTab.ClPtr))
|
|
|
- 3990 OR ((c1 = SymTab.ClPtr) AND (c2 = SymTab.ClProc)) THEN
|
|
|
- 3991 t := vt
|
|
|
- 3992 ELSIF (c1 = SymTab.ClReal)
|
|
|
- 3993 AND (c2 = SymTab.ClReal) THEN
|
|
|
- 3994 t := vt
|
|
|
- 3995 ELSIF ((c1 = SymTab.ClSet) AND (c2 = SymTab.ClInt))
|
|
|
- 3996 OR ((c1 = SymTab.ClInt) AND (c2 = SymTab.ClSet)) THEN
|
|
|
- 3997 (* a set <-> its machine word (BITSET) *)
|
|
|
- 3998 t := vt
|
|
|
- 3999 ELSE SemError(230);
|
|
|
- 4000 t := SymTab.InvalidType
|
|
|
- 4001 END
|
|
|
- 4002 END
|
|
|
- 4003 END; .)
|
|
|
- 4004 | "(" Expr<et, q> ")" (. t := et; astIsLit := TRUE; .)
|
|
|
- 4005 | SetLit<st, sq> (. astIsLit := TRUE; t := st;
|
|
|
- 4006 QbeGen.CopyOp(sq, q); .)
|
|
|
- 4007 | ( "NOT" | "~" ) Fact<t2, q2> (. astNot := astCur;
|
|
|
- 4008 IF SymTab.BoolCheck(t2) THEN
|
|
|
- 4009 t := SymTab.BoolType()
|
|
|
- 4010 ELSE SemError(212);
|
|
|
- 4011 t := SymTab.InvalidType END;
|
|
|
- 4012 IF t # SymTab.InvalidType THEN
|
|
|
- 4013 QbeGen.CopyOp("@", q)
|
|
|
- 4014 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 4015 END;
|
|
|
- 4016 astIsLit := TRUE;
|
|
|
- 4017 astCur := AST.MakeUn(
|
|
|
- 4018 AST.NkUnary, AST.OpNot, astNot); .)
|
|
|
- 4019 )
|
|
|
- 4020 (. IF NOT astIsLit THEN astCur := AST.NoNode END; .)
|
|
|
- 4021 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
- 4022 (* Set literals are SET OF [0..255] (8 words); elements validated
|
|
|
- 4023 0..255 statically when foldable (222 otherwise), runtime trap
|
|
|
- 4024 for computed elements. Ranges always lower via SetRange. *)
|
|
|
- 4025 SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 4026 (. VAR astNode: AST.Node; .)
|
|
|
- 4027 = "{" (. t := SymTab.NewSet(
|
|
|
- 4028 SymTab.NewSubR(0, 255));
|
|
|
- 4029 astNode := AST.MakeNode(AST.NkSetLit);
|
|
|
- 4030 QbeGen.NewSetTemp(8, q);
|
|
|
- 4031 QbeGen.SetZero(q, 8); .)
|
|
|
- 4032 [ SetElem<t, q, astNode> { "," SetElem<t, q, astNode> } ]
|
|
|
- 4033 "}" (. astCur := astNode; .) .
|
|
|
- 4034 (* Typed brace constructor: TypeName{ elems } — BITSET{0} (a set)
|
|
|
- 4035 or ArrayName{...} (an array constructor, GNU Modula-2). The
|
|
|
- 4036 declared type sets the width (set) or element type (array). *)
|
|
|
- 4037 TypedBraceLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 4038 (. VAR nw: CARDINAL;
|
|
|
- 4039 astNode, astTail: AST.Node;
|
|
|
- 4040 savedCls: INTEGER; .)
|
|
|
- 4041 = "{" (. savedCls := braceCls;
|
|
|
- 4042 astNode := AST.MakeNode(AST.NkBraceLit);
|
|
|
- 4043 AST.SetTy(astNode, vt);
|
|
|
- 4044 astTail := astNode;
|
|
|
- 4045 IF vt = SymTab.InvalidType THEN
|
|
|
- 4046 braceCls := -1
|
|
|
- 4047 ELSE braceCls :=
|
|
|
- 4048 SymTab.ClassOf(vt)
|
|
|
- 4049 END;
|
|
|
- 4050 IF braceCls = SymTab.ClSet THEN
|
|
|
- 4051 IF vt = SymTab.InvalidType THEN
|
|
|
- 4052 nw := 8
|
|
|
- 4053 ELSE nw := SymTab.SetWords(vt);
|
|
|
- 4054 IF nw = 0 THEN nw := 8 END
|
|
|
- 4055 END;
|
|
|
- 4056 QbeGen.NewSetTemp(nw, q);
|
|
|
- 4057 QbeGen.SetZero(q, nw)
|
|
|
- 4058 ELSIF (braceCls =
|
|
|
- 4059 SymTab.ClArray)
|
|
|
- 4060 OR (braceCls =
|
|
|
- 4061 SymTab.ClRecord)
|
|
|
- 4062 OR (braceCls =
|
|
|
- 4063 SymTab.ClClass) THEN
|
|
|
- 4064 QbeGen.CtorBegin(vt)
|
|
|
- 4065 ELSE
|
|
|
- 4066 IF vt # SymTab.InvalidType THEN
|
|
|
- 4067 SemError(230) END;
|
|
|
- 4068 braceCls := -1
|
|
|
- 4069 END; .)
|
|
|
- 4070 [ BraceElem<vt, q, astNode, astTail>
|
|
|
- 4071 { "," BraceElem<vt, q, astNode, astTail> } ]
|
|
|
- 4072 "}" (. IF (braceCls = SymTab.ClArray)
|
|
|
+ 3969 ELSIF (c1 = SymTab.ClReal)
|
|
|
+ 3970 AND (c2 = SymTab.ClInt) THEN
|
|
|
+ 3971 QbeGen.ConvRI(q, qa);
|
|
|
+ 3972 QbeGen.CopyOp(qa, q);
|
|
|
+ 3973 t := vt
|
|
|
+ 3974 ELSIF (c1 = SymTab.ClReal)
|
|
|
+ 3975 AND (c2 = SymTab.ClLong) THEN
|
|
|
+ 3976 QbeGen.ConvRL(q, qa);
|
|
|
+ 3977 QbeGen.CopyOp(qa, q);
|
|
|
+ 3978 t := vt
|
|
|
+ 3979 ELSIF (c1 = SymTab.ClLong)
|
|
|
+ 3980 AND (c2 = SymTab.ClLong) THEN
|
|
|
+ 3981 t := vt
|
|
|
+ 3982 ELSIF ((c1 = SymTab.ClInt)
|
|
|
+ 3983 OR (c1 =
|
|
|
+ 3984 SymTab.ClChar)
|
|
|
+ 3985 OR (c1 =
|
|
|
+ 3986 SymTab.ClBool)
|
|
|
+ 3987 OR (c1 =
|
|
|
+ 3988 SymTab.ClEnum))
|
|
|
+ 3989 AND ((c2 = SymTab.ClInt)
|
|
|
+ 3990 OR (c2 =
|
|
|
+ 3991 SymTab.ClChar)
|
|
|
+ 3992 OR (c2 =
|
|
|
+ 3993 SymTab.ClBool)
|
|
|
+ 3994 OR (c2 =
|
|
|
+ 3995 SymTab.ClEnum)) THEN
|
|
|
+ 3996 t := vt
|
|
|
+ 3997 ELSIF (c1 = SymTab.ClPtr)
|
|
|
+ 3998 AND (c2 = SymTab.ClPtr) THEN
|
|
|
+ 3999 t := vt
|
|
|
+ 4000 ELSIF ((c1 = SymTab.ClProc)
|
|
|
+ 4001 AND (c2 = SymTab.ClProc))
|
|
|
+ 4002 OR ((c1 = SymTab.ClProc) AND (c2 = SymTab.ClPtr))
|
|
|
+ 4003 OR ((c1 = SymTab.ClPtr) AND (c2 = SymTab.ClProc)) THEN
|
|
|
+ 4004 t := vt
|
|
|
+ 4005 ELSIF (c1 = SymTab.ClReal)
|
|
|
+ 4006 AND (c2 = SymTab.ClReal) THEN
|
|
|
+ 4007 t := vt
|
|
|
+ 4008 ELSIF ((c1 = SymTab.ClSet) AND (c2 = SymTab.ClInt))
|
|
|
+ 4009 OR ((c1 = SymTab.ClInt) AND (c2 = SymTab.ClSet)) THEN
|
|
|
+ 4010 (* a set <-> its machine word (BITSET) *)
|
|
|
+ 4011 t := vt
|
|
|
+ 4012 ELSE SemError(230);
|
|
|
+ 4013 t := SymTab.InvalidType
|
|
|
+ 4014 END
|
|
|
+ 4015 END
|
|
|
+ 4016 END; .)
|
|
|
+ 4017 | "(" Expr<et, q> ")" (. t := et; astIsLit := TRUE; .)
|
|
|
+ 4018 | SetLit<st, sq> (. astIsLit := TRUE; t := st;
|
|
|
+ 4019 QbeGen.CopyOp(sq, q); .)
|
|
|
+ 4020 | ( "NOT" | "~" ) Fact<t2, q2> (. astNot := astCur;
|
|
|
+ 4021 IF SymTab.BoolCheck(t2) THEN
|
|
|
+ 4022 t := SymTab.BoolType()
|
|
|
+ 4023 ELSE SemError(212);
|
|
|
+ 4024 t := SymTab.InvalidType END;
|
|
|
+ 4025 IF t # SymTab.InvalidType THEN
|
|
|
+ 4026 QbeGen.CopyOp("@", q)
|
|
|
+ 4027 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 4028 END;
|
|
|
+ 4029 astIsLit := TRUE;
|
|
|
+ 4030 astCur := AST.MakeUn(
|
|
|
+ 4031 AST.NkUnary, AST.OpNot, astNot); .)
|
|
|
+ 4032 )
|
|
|
+ 4033 (. IF NOT astIsLit THEN astCur := AST.NoNode END; .)
|
|
|
+ 4034 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
+ 4035 (* Set literals are SET OF [0..255] (8 words); elements validated
|
|
|
+ 4036 0..255 statically when foldable (222 otherwise), runtime trap
|
|
|
+ 4037 for computed elements. Ranges always lower via SetRange. *)
|
|
|
+ 4038 SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 4039 (. VAR astNode: AST.Node; .)
|
|
|
+ 4040 = "{" (. t := SymTab.NewSet(
|
|
|
+ 4041 SymTab.NewSubR(0, 255));
|
|
|
+ 4042 astNode := AST.MakeNode(AST.NkSetLit);
|
|
|
+ 4043 QbeGen.NewSetTemp(8, q);
|
|
|
+ 4044 QbeGen.SetZero(q, 8); .)
|
|
|
+ 4045 [ SetElem<t, q, astNode> { "," SetElem<t, q, astNode> } ]
|
|
|
+ 4046 "}" (. astCur := astNode; .) .
|
|
|
+ 4047 (* Typed brace constructor: TypeName{ elems } — BITSET{0} (a set)
|
|
|
+ 4048 or ArrayName{...} (an array constructor, GNU Modula-2). The
|
|
|
+ 4049 declared type sets the width (set) or element type (array). *)
|
|
|
+ 4050 TypedBraceLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 4051 (. VAR nw: CARDINAL;
|
|
|
+ 4052 astNode, astTail: AST.Node;
|
|
|
+ 4053 savedCls: INTEGER; .)
|
|
|
+ 4054 = "{" (. savedCls := braceCls;
|
|
|
+ 4055 astNode := AST.MakeNode(AST.NkBraceLit);
|
|
|
+ 4056 AST.SetTy(astNode, vt);
|
|
|
+ 4057 astTail := astNode;
|
|
|
+ 4058 IF vt = SymTab.InvalidType THEN
|
|
|
+ 4059 braceCls := -1
|
|
|
+ 4060 ELSE braceCls :=
|
|
|
+ 4061 SymTab.ClassOf(vt)
|
|
|
+ 4062 END;
|
|
|
+ 4063 IF braceCls = SymTab.ClSet THEN
|
|
|
+ 4064 IF vt = SymTab.InvalidType THEN
|
|
|
+ 4065 nw := 8
|
|
|
+ 4066 ELSE nw := SymTab.SetWords(vt);
|
|
|
+ 4067 IF nw = 0 THEN nw := 8 END
|
|
|
+ 4068 END;
|
|
|
+ 4069 QbeGen.NewSetTemp(nw, q);
|
|
|
+ 4070 QbeGen.SetZero(q, nw)
|
|
|
+ 4071 ELSIF (braceCls =
|
|
|
+ 4072 SymTab.ClArray)
|
|
|
4073 OR (braceCls =
|
|
|
- 4074 SymTab.ClRecord)
|
|
|
+ 4074 SymTab.ClRecord)
|
|
|
4075 OR (braceCls =
|
|
|
- 4076 SymTab.ClClass) THEN
|
|
|
- 4077 QbeGen.CtorEnd(q)
|
|
|
- 4078 ELSIF braceCls # SymTab.ClSet THEN
|
|
|
- 4079 QbeGen.CopyOp("0", q)
|
|
|
- 4080 END;
|
|
|
- 4081 braceCls := savedCls; .)
|
|
|
- 4082 (. astCur := astNode; .) .
|
|
|
- 4083 BraceElem<vt: SymTab.TypeIndex; VAR sq: QbeGen.QVal;
|
|
|
- 4084 VAR node, tail: AST.Node>
|
|
|
- 4085 (. VAR et, et2: SymTab.TypeIndex;
|
|
|
- 4086 qe, q2: QbeGen.QVal;
|
|
|
- 4087 v, v2, reps, k: INTEGER;
|
|
|
- 4088 elem: SymTab.TypeIndex;
|
|
|
- 4089 lo: INTEGER;
|
|
|
- 4090 span: CARDINAL;
|
|
|
- 4091 cl, cl2: INTEGER;
|
|
|
- 4092 hasR, hasB: BOOLEAN;
|
|
|
- 4093 astEl: AST.Node; .)
|
|
|
- 4094 = (. hasR := FALSE; hasB := FALSE;
|
|
|
- 4095 reps := 1; .)
|
|
|
- 4096 Expr<et, qe> (. astEl := astCur; .)
|
|
|
- 4097 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
- 4098 AST.NkSubrange, 0, astEl, astCur);
|
|
|
- 4099 hasR := TRUE; .) ]
|
|
|
- 4100 [ "BY" Expr<et2, q2> (. hasB := TRUE; .) ]
|
|
|
- 4101 (. IF braceCls = SymTab.ClSet THEN
|
|
|
- 4102 IF hasB THEN SemError(230) END;
|
|
|
- 4103 lo := SymTab.SetBaseLo(vt);
|
|
|
- 4104 span := SymTab.SetCount(vt);
|
|
|
- 4105 IF (et = SymTab.InvalidType)
|
|
|
- 4106 OR (hasR AND (et2 =
|
|
|
- 4107 SymTab.InvalidType)) THEN
|
|
|
- 4108 ELSE cl :=
|
|
|
- 4109 SymTab.ClassOf(et);
|
|
|
- 4110 IF hasR THEN
|
|
|
- 4111 cl2 :=
|
|
|
- 4112 SymTab.ClassOf(et2)
|
|
|
- 4113 ELSE cl2 := SymTab.ClInt
|
|
|
- 4114 END;
|
|
|
- 4115 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
- 4116 OR (hasR AND NOT
|
|
|
- 4117 SymTab.SetElemClassOk(cl2))
|
|
|
- 4118 THEN
|
|
|
- 4119 SemError(222)
|
|
|
- 4120 ELSIF hasR
|
|
|
- 4121 AND SymTab.ConstInt(qe, v)
|
|
|
- 4122 AND SymTab.ConstInt(q2,
|
|
|
- 4123 v2)
|
|
|
- 4124 AND ((v < lo)
|
|
|
- 4125 OR (v2 < lo)
|
|
|
- 4126 OR (v >= lo +
|
|
|
- 4127 VAL(INTEGER, span))
|
|
|
- 4128 OR (v2 >= lo +
|
|
|
- 4129 VAL(INTEGER, span))
|
|
|
- 4130 OR (v > v2)) THEN
|
|
|
- 4131 SemError(222)
|
|
|
- 4132 ELSIF hasR THEN
|
|
|
- 4133 QbeGen.SetRange(sq, qe, q2,
|
|
|
- 4134 lo, span)
|
|
|
- 4135 ELSIF SymTab.ConstInt(qe,
|
|
|
- 4136 v)
|
|
|
+ 4076 SymTab.ClClass) THEN
|
|
|
+ 4077 QbeGen.CtorBegin(vt)
|
|
|
+ 4078 ELSE
|
|
|
+ 4079 IF vt # SymTab.InvalidType THEN
|
|
|
+ 4080 SemError(230) END;
|
|
|
+ 4081 braceCls := -1
|
|
|
+ 4082 END; .)
|
|
|
+ 4083 [ BraceElem<vt, q, astNode, astTail>
|
|
|
+ 4084 { "," BraceElem<vt, q, astNode, astTail> } ]
|
|
|
+ 4085 "}" (. IF (braceCls = SymTab.ClArray)
|
|
|
+ 4086 OR (braceCls =
|
|
|
+ 4087 SymTab.ClRecord)
|
|
|
+ 4088 OR (braceCls =
|
|
|
+ 4089 SymTab.ClClass) THEN
|
|
|
+ 4090 QbeGen.CtorEnd(q)
|
|
|
+ 4091 ELSIF braceCls # SymTab.ClSet THEN
|
|
|
+ 4092 QbeGen.CopyOp("0", q)
|
|
|
+ 4093 END;
|
|
|
+ 4094 braceCls := savedCls; .)
|
|
|
+ 4095 (. astCur := astNode; .) .
|
|
|
+ 4096 BraceElem<vt: SymTab.TypeIndex; VAR sq: QbeGen.QVal;
|
|
|
+ 4097 VAR node, tail: AST.Node>
|
|
|
+ 4098 (. VAR et, et2: SymTab.TypeIndex;
|
|
|
+ 4099 qe, q2: QbeGen.QVal;
|
|
|
+ 4100 v, v2, reps, k: INTEGER;
|
|
|
+ 4101 elem: SymTab.TypeIndex;
|
|
|
+ 4102 lo: INTEGER;
|
|
|
+ 4103 span: CARDINAL;
|
|
|
+ 4104 cl, cl2: INTEGER;
|
|
|
+ 4105 hasR, hasB: BOOLEAN;
|
|
|
+ 4106 astEl: AST.Node; .)
|
|
|
+ 4107 = (. hasR := FALSE; hasB := FALSE;
|
|
|
+ 4108 reps := 1; .)
|
|
|
+ 4109 Expr<et, qe> (. astEl := astCur; .)
|
|
|
+ 4110 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
+ 4111 AST.NkSubrange, 0, astEl, astCur);
|
|
|
+ 4112 hasR := TRUE; .) ]
|
|
|
+ 4113 [ "BY" Expr<et2, q2> (. hasB := TRUE; .) ]
|
|
|
+ 4114 (. IF braceCls = SymTab.ClSet THEN
|
|
|
+ 4115 IF hasB THEN SemError(230) END;
|
|
|
+ 4116 lo := SymTab.SetBaseLo(vt);
|
|
|
+ 4117 span := SymTab.SetCount(vt);
|
|
|
+ 4118 IF (et = SymTab.InvalidType)
|
|
|
+ 4119 OR (hasR AND (et2 =
|
|
|
+ 4120 SymTab.InvalidType)) THEN
|
|
|
+ 4121 ELSE cl :=
|
|
|
+ 4122 SymTab.ClassOf(et);
|
|
|
+ 4123 IF hasR THEN
|
|
|
+ 4124 cl2 :=
|
|
|
+ 4125 SymTab.ClassOf(et2)
|
|
|
+ 4126 ELSE cl2 := SymTab.ClInt
|
|
|
+ 4127 END;
|
|
|
+ 4128 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
+ 4129 OR (hasR AND NOT
|
|
|
+ 4130 SymTab.SetElemClassOk(cl2))
|
|
|
+ 4131 THEN
|
|
|
+ 4132 SemError(222)
|
|
|
+ 4133 ELSIF hasR
|
|
|
+ 4134 AND SymTab.ConstInt(qe, v)
|
|
|
+ 4135 AND SymTab.ConstInt(q2,
|
|
|
+ 4136 v2)
|
|
|
4137 AND ((v < lo)
|
|
|
- 4138 OR (v >= lo +
|
|
|
- 4139 VAL(INTEGER,
|
|
|
- 4140 span))) THEN
|
|
|
- 4141 SemError(222)
|
|
|
- 4142 ELSE QbeGen.SetBit(sq, qe,
|
|
|
- 4143 lo, span)
|
|
|
- 4144 END
|
|
|
- 4145 END
|
|
|
- 4146 ELSIF (braceCls = SymTab.ClArray)
|
|
|
- 4147 OR (braceCls =
|
|
|
- 4148 SymTab.ClRecord)
|
|
|
- 4149 OR (braceCls =
|
|
|
- 4150 SymTab.ClClass) THEN
|
|
|
- 4151 IF hasR THEN SemError(230) END;
|
|
|
- 4152 reps := 1;
|
|
|
- 4153 IF hasB THEN
|
|
|
- 4154 IF SymTab.ConstInt(q2, v2)
|
|
|
- 4155 AND (v2 >= 1) THEN
|
|
|
- 4156 reps := v2
|
|
|
- 4157 ELSE SemError(230)
|
|
|
- 4158 END
|
|
|
- 4159 END;
|
|
|
- 4160 k := 0;
|
|
|
- 4161 WHILE k < reps DO
|
|
|
- 4162 QbeGen.CtorElem(qe);
|
|
|
- 4163 INC(k)
|
|
|
- 4164 END
|
|
|
- 4165 END; .)
|
|
|
- 4166 (. (* the BY form repeats the
|
|
|
- 4167 element; keep the AST in
|
|
|
- 4168 step with CtorElem *)
|
|
|
- 4169 k := 0;
|
|
|
- 4170 WHILE k < reps DO
|
|
|
- 4171 AstAppend(AST.NkBlock,
|
|
|
- 4172 node, tail, astEl);
|
|
|
- 4173 INC(k)
|
|
|
- 4174 END; .) .
|
|
|
- 4175 SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal; node: AST.Node> (. VAR et, et2: SymTab.TypeIndex;
|
|
|
- 4176 qe, q2: QbeGen.QVal;
|
|
|
- 4177 v, v2: INTEGER;
|
|
|
- 4178 lo: INTEGER;
|
|
|
- 4179 span: CARDINAL;
|
|
|
- 4180 cl, cl2: INTEGER;
|
|
|
- 4181 hasR: BOOLEAN;
|
|
|
- 4182 astEl: AST.Node; .)
|
|
|
- 4183 = (. hasR := FALSE; .)
|
|
|
- 4184 Expr<et, qe> (. astEl := astCur; .)
|
|
|
- 4185 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
- 4186 AST.NkSubrange, 0, astEl, astCur);
|
|
|
- 4187 hasR := TRUE; .) ]
|
|
|
- 4188 (. lo := SymTab.SetBaseLo(st);
|
|
|
- 4189 span := SymTab.SetCount(st);
|
|
|
- 4190 IF (et = SymTab.InvalidType)
|
|
|
- 4191 OR (hasR AND (et2 =
|
|
|
- 4192 SymTab.InvalidType)) THEN
|
|
|
- 4193 ELSE cl :=
|
|
|
- 4194 SymTab.ClassOf(et);
|
|
|
- 4195 IF hasR THEN
|
|
|
- 4196 cl2 :=
|
|
|
- 4197 SymTab.ClassOf(et2)
|
|
|
- 4198 ELSE cl2 := SymTab.ClInt
|
|
|
- 4199 END;
|
|
|
- 4200 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
- 4201 OR (hasR AND NOT
|
|
|
- 4202 SymTab.SetElemClassOk(cl2))
|
|
|
- 4203 THEN
|
|
|
- 4204 SemError(222)
|
|
|
- 4205 ELSIF hasR
|
|
|
- 4206 AND SymTab.ConstInt(qe, v)
|
|
|
- 4207 AND SymTab.ConstInt(q2,
|
|
|
- 4208 v2)
|
|
|
- 4209 AND ((v < lo)
|
|
|
- 4210 OR (v2 < lo)
|
|
|
- 4211 OR (v >= lo +
|
|
|
- 4212 VAL(INTEGER, span))
|
|
|
- 4213 OR (v2 >= lo +
|
|
|
- 4214 VAL(INTEGER, span))
|
|
|
- 4215 OR (v > v2)) THEN
|
|
|
- 4216 SemError(222)
|
|
|
- 4217 ELSIF hasR THEN
|
|
|
- 4218 QbeGen.SetRange(sq, qe, q2,
|
|
|
- 4219 lo, span)
|
|
|
- 4220 ELSIF SymTab.ConstInt(qe,
|
|
|
- 4221 v)
|
|
|
+ 4138 OR (v2 < lo)
|
|
|
+ 4139 OR (v >= lo +
|
|
|
+ 4140 VAL(INTEGER, span))
|
|
|
+ 4141 OR (v2 >= lo +
|
|
|
+ 4142 VAL(INTEGER, span))
|
|
|
+ 4143 OR (v > v2)) THEN
|
|
|
+ 4144 SemError(222)
|
|
|
+ 4145 ELSIF hasR THEN
|
|
|
+ 4146 QbeGen.SetRange(sq, qe, q2,
|
|
|
+ 4147 lo, span)
|
|
|
+ 4148 ELSIF SymTab.ConstInt(qe,
|
|
|
+ 4149 v)
|
|
|
+ 4150 AND ((v < lo)
|
|
|
+ 4151 OR (v >= lo +
|
|
|
+ 4152 VAL(INTEGER,
|
|
|
+ 4153 span))) THEN
|
|
|
+ 4154 SemError(222)
|
|
|
+ 4155 ELSE QbeGen.SetBit(sq, qe,
|
|
|
+ 4156 lo, span)
|
|
|
+ 4157 END
|
|
|
+ 4158 END
|
|
|
+ 4159 ELSIF (braceCls = SymTab.ClArray)
|
|
|
+ 4160 OR (braceCls =
|
|
|
+ 4161 SymTab.ClRecord)
|
|
|
+ 4162 OR (braceCls =
|
|
|
+ 4163 SymTab.ClClass) THEN
|
|
|
+ 4164 IF hasR THEN SemError(230) END;
|
|
|
+ 4165 reps := 1;
|
|
|
+ 4166 IF hasB THEN
|
|
|
+ 4167 IF SymTab.ConstInt(q2, v2)
|
|
|
+ 4168 AND (v2 >= 1) THEN
|
|
|
+ 4169 reps := v2
|
|
|
+ 4170 ELSE SemError(230)
|
|
|
+ 4171 END
|
|
|
+ 4172 END;
|
|
|
+ 4173 k := 0;
|
|
|
+ 4174 WHILE k < reps DO
|
|
|
+ 4175 QbeGen.CtorElem(qe);
|
|
|
+ 4176 INC(k)
|
|
|
+ 4177 END
|
|
|
+ 4178 END; .)
|
|
|
+ 4179 (. (* the BY form repeats the
|
|
|
+ 4180 element; keep the AST in
|
|
|
+ 4181 step with CtorElem *)
|
|
|
+ 4182 k := 0;
|
|
|
+ 4183 WHILE k < reps DO
|
|
|
+ 4184 AstAppend(AST.NkBlock,
|
|
|
+ 4185 node, tail, astEl);
|
|
|
+ 4186 INC(k)
|
|
|
+ 4187 END; .) .
|
|
|
+ 4188 SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal; node: AST.Node> (. VAR et, et2: SymTab.TypeIndex;
|
|
|
+ 4189 qe, q2: QbeGen.QVal;
|
|
|
+ 4190 v, v2: INTEGER;
|
|
|
+ 4191 lo: INTEGER;
|
|
|
+ 4192 span: CARDINAL;
|
|
|
+ 4193 cl, cl2: INTEGER;
|
|
|
+ 4194 hasR: BOOLEAN;
|
|
|
+ 4195 astEl: AST.Node; .)
|
|
|
+ 4196 = (. hasR := FALSE; .)
|
|
|
+ 4197 Expr<et, qe> (. astEl := astCur; .)
|
|
|
+ 4198 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
+ 4199 AST.NkSubrange, 0, astEl, astCur);
|
|
|
+ 4200 hasR := TRUE; .) ]
|
|
|
+ 4201 (. lo := SymTab.SetBaseLo(st);
|
|
|
+ 4202 span := SymTab.SetCount(st);
|
|
|
+ 4203 IF (et = SymTab.InvalidType)
|
|
|
+ 4204 OR (hasR AND (et2 =
|
|
|
+ 4205 SymTab.InvalidType)) THEN
|
|
|
+ 4206 ELSE cl :=
|
|
|
+ 4207 SymTab.ClassOf(et);
|
|
|
+ 4208 IF hasR THEN
|
|
|
+ 4209 cl2 :=
|
|
|
+ 4210 SymTab.ClassOf(et2)
|
|
|
+ 4211 ELSE cl2 := SymTab.ClInt
|
|
|
+ 4212 END;
|
|
|
+ 4213 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
+ 4214 OR (hasR AND NOT
|
|
|
+ 4215 SymTab.SetElemClassOk(cl2))
|
|
|
+ 4216 THEN
|
|
|
+ 4217 SemError(222)
|
|
|
+ 4218 ELSIF hasR
|
|
|
+ 4219 AND SymTab.ConstInt(qe, v)
|
|
|
+ 4220 AND SymTab.ConstInt(q2,
|
|
|
+ 4221 v2)
|
|
|
4222 AND ((v < lo)
|
|
|
- 4223 OR (v >= lo +
|
|
|
- 4224 VAL(INTEGER,
|
|
|
- 4225 span))) THEN
|
|
|
- 4226 SemError(222)
|
|
|
- 4227 ELSE QbeGen.SetBit(sq, qe,
|
|
|
- 4228 lo, span)
|
|
|
- 4229 END
|
|
|
- 4230 END; .)
|
|
|
- 4231 (. AST.SetChild(node,
|
|
|
- 4232 AST.NChild(node), astEl); .) .
|
|
|
- 4233 GetIdent<VAR n: SymTab.Name>
|
|
|
- 4234 = ident (. LexName(n); .) .
|
|
|
- 4235
|
|
|
- 4236 END M2.
|
|
|
+ 4223 OR (v2 < lo)
|
|
|
+ 4224 OR (v >= lo +
|
|
|
+ 4225 VAL(INTEGER, span))
|
|
|
+ 4226 OR (v2 >= lo +
|
|
|
+ 4227 VAL(INTEGER, span))
|
|
|
+ 4228 OR (v > v2)) THEN
|
|
|
+ 4229 SemError(222)
|
|
|
+ 4230 ELSIF hasR THEN
|
|
|
+ 4231 QbeGen.SetRange(sq, qe, q2,
|
|
|
+ 4232 lo, span)
|
|
|
+ 4233 ELSIF SymTab.ConstInt(qe,
|
|
|
+ 4234 v)
|
|
|
+ 4235 AND ((v < lo)
|
|
|
+ 4236 OR (v >= lo +
|
|
|
+ 4237 VAL(INTEGER,
|
|
|
+ 4238 span))) THEN
|
|
|
+ 4239 SemError(222)
|
|
|
+ 4240 ELSE QbeGen.SetBit(sq, qe,
|
|
|
+ 4241 lo, span)
|
|
|
+ 4242 END
|
|
|
+ 4243 END; .)
|
|
|
+ 4244 (. AST.SetChild(node,
|
|
|
+ 4245 AST.NChild(node), astEl); .) .
|
|
|
+ 4246 GetIdent<VAR n: SymTab.Name>
|
|
|
+ 4247 = ident (. LexName(n); .) .
|
|
|
+ 4248
|
|
|
+ 4249 END M2.
|
|
|
|
|
|
0 errors
|
|
|
|