1/* BEGIN LICENSE BLOCK 2 * Version: CMPL 1.1 3 * 4 * The contents of this file are subject to the Cisco-style Mozilla Public 5 * License Version 1.1 (the "License"); you may not use this file except 6 * in compliance with the License. You may obtain a copy of the License 7 * at www.eclipse-clp.org/license. 8 * 9 * Software distributed under the License is distributed on an "AS IS" 10 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 11 * the License for the specific language governing rights and limitations 12 * under the License. 13 * 14 * The Original Code is The ECLiPSe Constraint Logic Programming System. 15 * The Initial Developer of the Original Code is Cisco Systems, Inc. 16 * Portions created by the Initial Developer are 17 * Copyright (C) 1989-2006 Cisco Systems, Inc. All Rights Reserved. 18 * 19 * Contributor(s): 20 * 21 * END LICENSE BLOCK */ 22 23 24/* 25 * SEPIA C SOURCE MODULE 26 * 27 * VERSION $Id: operator.c,v 1.6 2012/09/23 18:52:39 jschimpf Exp $ 28 */ 29 30/* 31 * IDENTIFICATION operator.c 32 * 33 * DESCRIPTION implemetation of the operator using 34 * the property list 35 * 36 * CONTENTS: 37 * 38 * AUTHOR VERSION DATE REASON 39 * Emmanuel van Rossum 900315 created the file 40 * 41 */ 42 43#include "config.h" 44#include "sepia.h" 45#include "types.h" 46#include "embed.h" 47#include "error.h" 48#include "mem.h" 49#include "dict.h" 50#include "emu_export.h" 51#include "property.h" 52#include "module.h" 53#include "lex.h" 54 55 56 57/* flags in the isop field of atoms, not set means no operator, 58 set means may be an operator */ 59#define IS_PREFIX_OP 1 60#define IS_INFIX_OP 2 61#define IS_POSTFIX_OP 4 62 63#define FixToProp(fixity) ((fixity) == IS_PREFIX_OP ? PREFIX_PROP : (fixity) == IS_INFIX_OP ? INFIX_PROP : POSTFIX_PROP) 64 65#define PropToFix(prop) ((prop) == PREFIX_PROP ? IS_PREFIX_OP : (prop) == INFIX_PROP ? IS_INFIX_OP : IS_POSTFIX_OP) 66 67/* 2 followings get or create a property prop (can be PREFIX_PROP or 68 INFIX_PROP or POSTFIX_PROP) for did did in module mod with visibility vis */ 69#define OperatorItem(did, mod, mod_tag, vis, prop, perr) \ 70 get_modular_property(did, prop, mod, mod_tag, vis, perr) 71#define NewOperatorItem(did, mod, mod_tag, vis, prop, perr) \ 72 set_modular_property(did, prop, mod, mod_tag, vis, perr) 73 74 75static dident didassoc[MAX_ASSOC+1]; 76static dident d_comma0_, d_bar0_; 77 78static int 79 _get_assoc(dident assoc), 80 _insert_op(int scope, word preced, word assoc, dident oper, dident module, type mod_tag), 81 _erase_op(dident oper, word assoc, int scope, dident module, type mod_tag), 82 p_op_(value vi, type ti, value vprec, type tprec, value vassoc, type tassoc, value v_op, type t_op, value vm, type tm), 83 p_is_prefix_op(value vp, type tp, value assoc, type ta, value name, type tn, value vv, type tv, value module, type tm), 84 p_is_postfix_op(value vp, type tp, value assoc, type ta, value name, type tn, value vv, type tv, value module, type tm), 85 p_is_infix_op(value vp, type tp, value assoc, type ta, value name, type tn, value vv, type tv, value module, type tm), 86 p_abolish_op_(value v_op, type t_op, value v_assoc, type t_assoc, value v_mod, type t_mod), 87 p_legal_current_op(value v_prec, type t_prec, value v_assoc, type t_assoc, value v_op, type t_op, value v_mod, type t_mod); 88 89static opi *_visible_anyfix_op(int fixity, dident atom, dident module, type mod_tag, int *res); 90 91 92/* 93 * Operator Initialization 94 */ 95/*ARGSUSED*/ 96void 97op_init(int flags) 98{ 99 if (!(flags & INIT_PRIVATE)) 100 return; 101 /* initialize the associativity table */ 102 didassoc[FX] = in_dict("fx", 0); 103 didassoc[FY] = in_dict("fy", 0); 104 didassoc[XF] = in_dict("xf", 0); 105 didassoc[YF] = in_dict("yf", 0); 106 didassoc[XFX] = in_dict("xfx", 0); 107 didassoc[XFY] = in_dict("xfy", 0); 108 didassoc[YFX] = in_dict("yfx", 0); 109 didassoc[FXX] = in_dict("fxx", 0); 110 didassoc[FXY] = in_dict("fxy", 0); 111 112 d_comma0_ = in_dict(",", 0); 113 d_bar0_ = in_dict("|", 0); 114} 115 116void 117bip_op_init(int flags) 118{ 119 if (!(flags & INIT_SHARED)) 120 return; 121 (void) local_built_in(in_dict("op_", 5), p_op_, B_SAFE); 122 (void) local_built_in(in_dict("is_prefix_op", 5), p_is_prefix_op, B_SAFE); 123 (void) local_built_in(in_dict("is_postfix_op", 5), p_is_postfix_op, B_SAFE); 124 (void) local_built_in(in_dict("is_infix_op", 5), p_is_infix_op, B_SAFE); 125 (void) local_built_in(in_dict("abolish_op_", 3),p_abolish_op_, B_SAFE); 126 (void) local_built_in(in_dict("legal_current_op", 4), 127 p_legal_current_op, B_SAFE); 128} 129 130/* 131 * returns the (unsigned) associativity associated to the 132 * Prolog one (did). 133 * return NIL_OP if 'assoc' is not in the table. 134 */ 135static int 136_get_assoc(dident assoc) 137{ 138 word iassoc = MAX_ASSOC; 139 140 while (iassoc > NIL_OP && didassoc[iassoc] != assoc) 141 iassoc--; 142 return (iassoc); 143} 144 145/* 146 * The locking done here is rather useless: 147 * We are not allowed to return a pointer to a (shared heap) opi 148 * without holding the lock. But this would be just too much to fix... 149 * Most of the other properties have the same bug. 150 */ 151static opi * 152_visible_anyfix_op(int fixity, dident atom, dident module, type mod_tag, int *res) 153{ 154 opi *operator_prop; 155 156 if (atom == D_UNKNOWN 157 || !(DidIsOp(atom) & fixity)) 158 { 159 *res = PERROR; 160 return 0; 161 } 162 163 a_mutex_lock(&PropertyLock); 164 165 operator_prop = OperatorItem(atom, module, mod_tag, 166 VISIBLE_PROP, FixToProp(fixity), res); 167 if (!operator_prop) 168 { 169 a_mutex_unlock(&PropertyLock); 170 *res = PERROR; 171 return 0; 172 } 173 if (operator_prop->tag.kernel != TEND) 174 { 175 a_mutex_unlock(&PropertyLock); /* THIS IS WRONG! */ 176 return operator_prop; 177 } 178 else 179 { 180 a_mutex_unlock(&PropertyLock); 181 *res = PERROR; 182 return 0; 183 } 184} 185 186 187/* 188 * Return nonzero if any operator property is attached to atom. 189 * Needed to implement ISO-Prolog restrictions. 190 */ 191int 192visible_operator(dident atom, dident module, type mod_tag) 193{ 194 int res; 195 opi *desc; 196 desc = OperatorItem(atom, module, mod_tag, VISIBLE_PROP, INFIX_PROP, &res); 197 if (desc && GetOpiPreced(desc)) return 1; 198 desc = OperatorItem(atom, module, mod_tag, VISIBLE_PROP, PREFIX_PROP, &res); 199 if (desc && GetOpiPreced(desc)) return 1; 200 desc = OperatorItem(atom, module, mod_tag, VISIBLE_PROP, POSTFIX_PROP, &res); 201 if (desc && GetOpiPreced(desc)) return 1; 202 return 0; 203} 204 205 206/* 207 * visible_prefix_op(atom, module) return a pointer to the visible 208 * prefix operator desriptor defined under atom and visible from module 209 * if there is such an operator; return 0 otherwise. 210 */ 211opi* 212visible_prefix_op(dident atom, dident module, type mod_tag, int *res) 213{ 214 opi *desc; 215 216 desc = _visible_anyfix_op(IS_PREFIX_OP, atom, module, mod_tag, res); 217 if (desc && !GetOpiPreced(desc)) { 218 *res = PERROR; 219 return (opi *) 0; 220 } else 221 return desc; 222} 223 224/* 225 * visible_infix_op(atom, module) return a pointer to the visible 226 * infix operator desriptor defined under atom and visible from module 227 * if there is such an operator; return 0 otherwise. 228 */ 229opi* 230visible_infix_op(dident atom, dident module, type mod_tag, int *res) 231{ 232 opi *desc; 233 234 desc = _visible_anyfix_op(IS_INFIX_OP, atom, module, mod_tag, res); 235 if (desc && !GetOpiPreced(desc)) { 236 *res = PERROR; 237 return (opi *) 0; 238 } else 239 return desc; 240} 241 242/* 243 * visible_postfix_op(atom, module) return a pointer to the visible 244 * postfix operator desriptor defined under atom and visible from module 245 * if there is such an operator; return 0 otherwise. 246 */ 247opi* 248visible_postfix_op(dident atom, dident module, type mod_tag, int *res) 249{ 250 opi *desc; 251 252 desc = _visible_anyfix_op(IS_POSTFIX_OP, atom, module, mod_tag, res); 253 if (desc && !GetOpiPreced(desc)) { 254 *res = PERROR; 255 return (opi *) 0; 256 } else 257 return desc; 258} 259 260/* 261 * visible_op(functor, module) return a pointer to the visible operator 262 * under functor (an infix operator if functor is arity 2, an unary operator 263 * if functor is of arity 1 (if a prefix and a postfix are visible, 264 * the prefix is returned). 265 * return 0 if no operator is visible from module under functor. 266 * NOTE : when there is a prefix/postfix conflict, a local declaration 267 * should be return when there is one (e.g. local postfix and global prefix). 268 */ 269opi* 270visible_op(dident functor, dident module, type mod_tag, int *res) 271{ 272 opi *operator_prop; 273 int arity; 274 dident atom = add_dict(functor, 0); 275 276 if ((arity = DidArity(functor)) == 1) 277 { 278 /* look for a unary operator: first try FX,FY then XF,YF */ 279 operator_prop = visible_prefix_op(atom, module, mod_tag, res); 280 /* visible_prefix_op() also finds FXX and FXY: ignore them here */ 281 if (!operator_prop || IsPrefix2(operator_prop)) 282 { 283 /* no unary prefix, look for postfix */ 284 operator_prop = visible_postfix_op(atom, module, mod_tag, res); 285 } 286 } 287 else if (arity == 2) 288 { 289 /* look for a binary operator, first try XFX,XFY,YFX then FXX,FXY */ 290 operator_prop = visible_infix_op(atom, module, mod_tag, res); 291 if (!operator_prop) 292 { 293 /* no infix, look for binary prefix */ 294 operator_prop = visible_prefix_op(atom, module, mod_tag, res); 295 if (operator_prop && !IsPrefix2(operator_prop)) 296 operator_prop = (opi *) 0; 297 } 298 } 299 else /* arity != 1 && arity != 2 so it is not an operator */ 300 { 301 *res = PERROR; /* means no operator */ 302 return 0; 303 } 304 return operator_prop; 305} 306 307/* 308 * is_visible_op(atom, module, mod_tag) returns 1 iff there is an 309 * operator attached to 'atom', returns 0 otherwise. 310 * 311 * Must be called in an interrupt protected area. 312 */ 313int 314is_visible_op(dident atom, dident module, type mod_tag) 315{ 316 opi *operator_prop; 317 int err = PERROR; 318 int res; 319 320 if (atom == D_UNKNOWN || !DidIsOp(atom)) 321 { 322 Set_Bip_Error(PERROR); 323 return 0; 324 } 325 326 a_mutex_lock(&PropertyLock); 327 328 /* DidIsOp may be out of date, ie. it may be set even when there 329 * is no longer such an operator. That's why we have to check. */ 330 if ((DidIsOp(atom) & IS_PREFIX_OP) 331 && (operator_prop = OperatorItem(atom, module, mod_tag, 332 VISIBLE_PROP, PREFIX_PROP, &res)) 333 && operator_prop->tag.kernel != TEND 334 && GetOpiPreced(operator_prop)) 335 { 336 a_mutex_unlock(&PropertyLock); 337 return 1; 338 } 339 else if ((DidIsOp(atom) & IS_INFIX_OP) 340 && (operator_prop = OperatorItem(atom, module, mod_tag, 341 VISIBLE_PROP, INFIX_PROP,&res)) 342 && operator_prop->tag.kernel != TEND 343 && GetOpiPreced(operator_prop)) 344 { 345 a_mutex_unlock(&PropertyLock); 346 return 1; 347 } 348 else if ((DidIsOp(atom) & IS_POSTFIX_OP) 349 && (operator_prop = OperatorItem(atom, module, mod_tag, 350 VISIBLE_PROP, POSTFIX_PROP,&res)) 351 && operator_prop->tag.kernel != TEND 352 && GetOpiPreced(operator_prop)) 353 { 354 a_mutex_unlock(&PropertyLock); 355 return 1; 356 } 357 else 358 { 359 Set_Bip_Error(err); 360 a_mutex_unlock(&PropertyLock); 361 return 0; 362 } 363} 364 365 366/* The following builtins use the global error variable ! */ 367#undef Bip_Error 368#define Bip_Error(N) Bip_Error_Fail(N) 369 370/* 371 op_(Visibility, Precedence, Associativity, Operator, Module) 372 It inserts in the operator table an operator, whose name is 373 Operator of precedence Precedence and of associativity Associativity. 374 Visibility can only be global or local. Module is significant 375 only for a local operator. 376 A null precedence will erase/hide a previous/global declaration. 377 */ 378/*ARGSUSED*/ 379static int 380p_op_(value vi, type ti, value vprec, type tprec, value vassoc, type tassoc, value v_op, type t_op, value vm, type tm) 381{ 382 word iassoc; 383 int scope = (vi.did == d_.local0 ? LOCAL_PROP : GLOBAL_PROP); 384 385 /* vi is supplied by the system so no need to test it. */ 386 Check_Module(tm, vm); 387 Check_Atom_Or_Nil(v_op, t_op); 388 Check_Atom_Or_Nil(vassoc, tassoc); 389 Check_Integer(tprec); 390 391 if ((vprec.nint > 1200) || (vprec.nint < 0)) 392 { 393 Bip_Error(RANGE_ERROR); 394 } 395 iassoc = _get_assoc(vassoc.did); 396 if (iassoc == NIL_OP) 397 { 398 Bip_Error(RANGE_ERROR); 399 } 400 if (ModuleSyntax(vm.did)->options & ISO_RESTRICTIONS) 401 { 402 if (iassoc >= FXX) 403 { 404 Bip_Error(RANGE_ERROR) 405 } 406 else if (v_op.did == d_comma0_ 407 || v_op.did == d_.nil 408 || v_op.did == d_.nilcurbr 409 || v_op.did == d_bar0_ && ( 410 !(iassoc==XFY || iassoc==XFX || iassoc==YFX) 411 || vprec.nint > 0 && vprec.nint <= 1000)) 412 { 413 Bip_Error(ILLEGAL_OP_DEF) 414 } 415 } 416 417 if (vprec.nint == 0 && scope == GLOBAL_PROP) 418 /* precedence 0 is used to erase the operator but if it is 419 local, the descriptor is kept to hide a global operator */ 420 return _erase_op(v_op.did, iassoc, scope, vm.did, tm); 421 else 422 return _insert_op(scope, vprec.nint, iassoc, v_op.did, vm.did, tm); 423} 424 425/* 426 abolish_op_(atom, assoc, module) 427 abolish the declaration of the operator 'atom' of associativity 428 'assoc' visible from 'module'. 429 */ 430static int 431p_abolish_op_(value v_op, type t_op, value v_assoc, type t_assoc, value v_mod, type t_mod) 432{ 433 word iassoc; 434 435 Check_Atom_Or_Nil(v_op, t_op); 436 Check_Atom_Or_Nil(v_assoc, t_assoc); 437 Check_Module(t_mod, v_mod); 438 439 iassoc = _get_assoc(v_assoc.did); 440 if (iassoc == NIL_OP) 441 { 442 Bip_Error(RANGE_ERROR); 443 } 444 445 return _erase_op(v_op.did, iassoc, VISIBLE_PROP, v_mod.did,t_mod); 446} 447 448/* 449 _insert_op( scope, preced, assoc, oper, module, mod_tag) 450 An insertion is made in the operator property list if there are 451 no conflict of associativity (postfix and infix). 452 However a local postfix/infix hide a global one so that 453 the conflict is impossible between a local and a global. 454 A local operator can not be modified in a locked module if the 455 module tag is not signed. 456 The precedence 0 is used to hide a global operator. 457*/ 458static int 459_insert_op(int scope, word preced, word assoc, dident oper, dident module, type mod_tag) 460{ 461 opi *operator_prop; 462 int prop_type; 463 int arity; 464 int res; 465 466 switch (assoc) 467 { 468 case XF: 469 case YF: 470 prop_type = POSTFIX_PROP; 471 arity = 1; 472 break; 473 case FX: 474 case FY: 475 prop_type = PREFIX_PROP; 476 arity = 1; 477 break; 478 case FXX: 479 case FXY: 480 prop_type = PREFIX_PROP; 481 arity = 2; 482 break; 483 case XFX: 484 case XFY: 485 case YFX: 486 prop_type = INFIX_PROP; 487 arity = 2; 488 break; 489 } 490 491 /* Disallow infix/postfix, if required by the module syntax */ 492 if (prop_type != PREFIX_PROP && ModuleSyntax(module)->options & ISO_RESTRICTIONS) 493 { 494 if (OperatorItem(oper, module, mod_tag, VISIBLE_PROP, 495 (prop_type==INFIX_PROP? POSTFIX_PROP : INFIX_PROP), &res)) 496 { 497 Bip_Error(ILLEGAL_OP_DEF); 498 } 499 } 500 501 a_mutex_lock(&PropertyLock); 502 503 res = PERROR; 504 operator_prop = OperatorItem(oper, module, mod_tag, scope, prop_type, &res); 505 506 if (operator_prop) /* same scope operator exists already */ 507 { 508 if (preced && (GetOpiAssoc(operator_prop) != assoc || 509 GetOpiPreced(operator_prop) != preced)) { 510 res = REDEF_OPERATOR; 511 } else { 512 res = PSUCCEED; 513 } 514 } 515 else 516 { 517 if (res != PERROR) 518 { 519 a_mutex_unlock(&PropertyLock); 520 Bip_Error(res); 521 } 522 /* No proper scope operator exists yet */ 523 /* For locals, check hiding */ 524 if (scope == LOCAL_PROP && 525 OperatorItem(oper, module, mod_tag, GLOBAL_PROP, prop_type, &res)) 526 res = HIDING_OPERATOR; 527 else 528 res = PSUCCEED; 529 530 operator_prop = NewOperatorItem(oper, module, mod_tag, 531 scope, prop_type, &res); 532 if (!operator_prop) 533 { 534 a_mutex_unlock(&PropertyLock); 535 Bip_Error(res); 536 } 537 } 538 539 /* now update the descriptor */ 540 operator_prop->tag.kernel = TDICT; 541 Set_Opi_Assoc(operator_prop, assoc); 542 Set_Opi_Preced(operator_prop, preced); 543 OpiDid(operator_prop) = add_dict(oper, arity); 544 DidIsOp(oper) |= PropToFix(prop_type); 545 546 a_mutex_unlock(&PropertyLock); 547 if (res < 0) 548 {Bip_Error(res)} 549 return res; 550} 551 552/* 553 * _erase_op(oper, module) erase the definition of an operator 554 */ 555static int 556_erase_op(dident oper, word assoc, int scope, dident module, type mod_tag) 557{ 558 opi *operator_prop; 559 int prop_type; 560 int res; 561 562 switch (assoc) 563 { 564 case XF: 565 case YF: 566 prop_type = POSTFIX_PROP; 567 break; 568 case FX: 569 case FY: 570 case FXX: 571 case FXY: 572 prop_type = PREFIX_PROP; 573 break; 574 case XFX: 575 case XFY: 576 case YFX: 577 prop_type = INFIX_PROP; 578 break; 579 } 580 581 a_mutex_lock(&PropertyLock); 582 operator_prop = OperatorItem(oper, module, mod_tag, scope, prop_type,&res); 583 if (!operator_prop) 584 { 585 if (res == PERROR) 586 res = UNDEF_OPERATOR; 587 a_mutex_unlock(&PropertyLock); 588 Bip_Error(res); 589 } 590 else if (operator_prop->tag.kernel == TEND) 591 { 592 a_mutex_unlock(&PropertyLock); 593 Bip_Error(UNDEF_OPERATOR); 594 } 595 if (erase_modular_property(oper, prop_type, module, mod_tag, scope) 596 == PFAIL) /* the property is completely erased for that atom */ 597 { 598 DidIsOp(oper) &= ~PropToFix(prop_type); 599 } 600 a_mutex_unlock(&PropertyLock); 601 Succeed_; 602} 603 604/* 605 legal_current_op(?Precedence, ?Assoc, +Operator_atom, +Module) 606 checks that all arguments are valid for current_op_body/4. 607 */ 608static int 609p_legal_current_op(value v_prec, type t_prec, value v_assoc, type t_assoc, value v_op, type t_op, value v_mod, type t_mod) 610{ 611 if (!IsRef(t_op)) /* Operator name */ 612 { 613 Check_Atom_Or_Nil(v_op, t_op); 614#ifdef lint 615 /* v_op is set in Check_Atom_Or_Nil but not used */ 616 if (v_op.nint) return v_op.nint; 617#endif /* lint */ 618 } 619 Check_Module(t_mod, v_mod); /* module */ 620 Check_Module_Access(v_mod, t_mod); 621 622 if (IsAtom(t_assoc)) /* Associativity */ 623 { 624 word iassoc = _get_assoc(v_assoc.did); 625 if (iassoc == NIL_OP || 626 (iassoc > FXX && (ModuleSyntax(v_mod.did)->options & ISO_RESTRICTIONS))) 627 { 628 Bip_Error(RANGE_ERROR); 629 } 630 } 631 else if (!IsRef(t_assoc)) 632 { 633 Bip_Error(TYPE_ERROR); 634 } 635 636 if (IsInteger(t_prec)) /* Precedence */ 637 { 638 if (v_prec.nint < 0 || v_prec.nint > 1200) 639 { 640 Bip_Error(RANGE_ERROR); 641 } 642 } 643 else if (!IsRef(t_prec)) 644 { 645 Bip_Error(TYPE_ERROR); 646 } 647 Succeed_; 648} 649 650/* 651 is_prefix_op(Precedence, Associativity, Name, Visib, Module) 652 Name and Module must be instantiated. 653 Associativity and Precedence are either instantiated or a variable. 654 If there is an operator of this type in the operator table, 655 It succeeds and instantiates the precedence. 656*/ 657/*ARGSUSED*/ /* check is already made in p_illegal_current_op */ 658static int 659p_is_prefix_op(value vp, type tp, value assoc, type ta, value name, type tn, value vv, type tv, value module, type tm) 660{ 661 opi *desc; 662 int res; 663 Prepare_Requests; 664 665 if (IsNil(tn)) 666 { 667 name.did = d_.nil; 668 tn = tdict; 669 } 670 671 if (desc = _visible_anyfix_op(IS_PREFIX_OP, name.did, module.did, tm, &res)) 672 { 673 Request_Unify_Integer(vp, tp, GetOpiPreced(desc)); 674 Request_Unify_Atom(assoc, ta, didassoc[GetOpiAssoc(desc)]); 675 Request_Unify_Atom(vv, tv, 676 (res == LOCAL_PROP ? d_.local0 : d_.global0)); 677 Return_Unify; 678 } 679 Fail_; 680} 681 682/* 683 is_postfix_op(Precedence, Associativity, Name, Visib, Module) 684 Name and Module must be instantiated. 685 Associativity and Precedence are either instantiated or a variable. 686 If there is an operator of this type in the operator table, 687 It succeeds and instantiates the precedence. 688*/ 689/*ARGSUSED*/ /* check is already made in p_illegal_current_op */ 690static int 691p_is_postfix_op(value vp, type tp, value assoc, type ta, value name, type tn, value vv, type tv, value module, type tm) 692{ 693 opi *desc; 694 int res; 695 Prepare_Requests 696 697 if (IsNil(tn)) 698 { 699 name.did = d_.nil; 700 tn = tdict; 701 } 702 if (desc = _visible_anyfix_op(IS_POSTFIX_OP, name.did, module.did, tm, &res)) 703 { 704 Request_Unify_Integer(vp, tp, GetOpiPreced(desc)); 705 Request_Unify_Atom(assoc, ta, didassoc[GetOpiAssoc(desc)]); 706 Request_Unify_Atom(vv, tv, 707 (res == LOCAL_PROP ? d_.local0 : d_.global0)); 708 Return_Unify; 709 } 710 Fail_; 711} 712 713/* 714 is_infix_op(Precedence, Associativity, Name, Visib, Module) 715 Name and Module must be instantiated. 716 Associativity and Precedence are either instantiated or a variable. 717 If there is an operator of this type in the operator table, 718 It succeeds and instantiates the precedence. 719*/ 720/*ARGSUSED*/ /* check is already made in p_illegal_current_op */ 721static int 722p_is_infix_op(value vp, type tp, value assoc, type ta, value name, type tn, value vv, type tv, value module, type tm) 723{ 724 opi *desc; 725 int res; 726 Prepare_Requests 727 728 if (IsNil(tn)) 729 { 730 name.did = d_.nil; 731 tn = tdict; 732 } 733 if (desc = _visible_anyfix_op(IS_INFIX_OP, name.did, module.did, tm, &res)) 734 { 735 Request_Unify_Integer(vp, tp, GetOpiPreced(desc)); 736 Request_Unify_Atom(assoc, ta, didassoc[GetOpiAssoc(desc)]); 737 Request_Unify_Atom(vv, tv, 738 (res == LOCAL_PROP ? d_.local0 : d_.global0)); 739 Return_Unify; 740 } 741 Fail_; 742} 743