PageRenderTime 58ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/Languages/IronPython/Scripts/generate_ops.py

http://github.com/IronLanguages/main
Python | 672 lines | 653 code | 4 blank | 15 comment | 0 complexity | eb9c0baa80068f8dd74a19764303abda MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. #####################################################################################
  2. #
  3. # Copyright (c) Microsoft Corporation. All rights reserved.
  4. #
  5. # This source code is subject to terms and conditions of the Apache License, Version 2.0. A
  6. # copy of the license can be found in the License.html file at the root of this distribution. If
  7. # you cannot locate the Apache License, Version 2.0, please send an email to
  8. # ironpy@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. # by the terms of the Apache License, Version 2.0.
  10. #
  11. # You must not remove this notice, or any other, from this software.
  12. #
  13. #
  14. #####################################################################################
  15. from generate import generate
  16. import operator
  17. # Add new keywords to the end of the list to preserve existing Enum values
  18. kwlist = [
  19. 'and', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'exec',
  20. 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'not', 'or', 'pass',
  21. 'print', 'raise', 'return', 'try', 'while', 'yield', 'as', 'with'
  22. ]
  23. class Symbol:
  24. def __init__(self, symbol, name, titleName = None):
  25. self.symbol = symbol
  26. self.name = name
  27. self.titleName = titleName
  28. def cap_name(self):
  29. return self.name.title().replace(' ', '')
  30. def upper_name(self):
  31. return self.name.upper().replace(' ', '_')
  32. def title_name(self):
  33. if not self.titleName: return self.name.title().replace(' ', '')
  34. return self.titleName
  35. def simple_name(self):
  36. return self.name[0] + self.cap_name()[1:]
  37. def symbol_name(self):
  38. return "Operator" + self.title_name()
  39. def reverse_symbol_name(self):
  40. return "OperatorReverse" + self.title_name()
  41. def inplace_symbol_name(self):
  42. return "OperatorInPlace" + self.title_name()
  43. def __repr__(self):
  44. return 'Symbol(%s)' % self.symbol
  45. def is_comparison(self):
  46. return self.symbol in (sym for sym, name, rname,clrName,opposite, bool1, bool2, bool3 in compares)
  47. def is_bitwise(self):
  48. return self.symbol in ['^', '&', '|', '<<', '>>']
  49. class Operator(Symbol):
  50. def __init__(self, symbol, name, rname, clrName=None,prec=-1, opposite=None, bool1=None, bool2=None, bool3=None, dotnetOp=False):
  51. Symbol.__init__(self, symbol, name)
  52. self.rname = rname
  53. self.clrName = clrName
  54. self.dotnetOp = dotnetOp
  55. self.meth_name = "__" + name + "__"
  56. self.rmeth_name = "__" + rname + "__"
  57. if name in kwlist:
  58. name = name + "_"
  59. #self.op = getattr(operator, name)
  60. self.prec = prec
  61. self.opposite = opposite
  62. self.bool1 = bool1
  63. self.bool2 = bool2
  64. self.bool3 = bool3
  65. def clrInPlaceName(self):
  66. return "InPlace" + self.clrName
  67. def title_name(self):
  68. return self.clrName
  69. def isCompare(self):
  70. return self.prec == -1
  71. def __repr__(self):
  72. return 'Operator(%s,%s,%s)' % (self.symbol, self.name, self.rname)
  73. def genOperatorTable_Mapping(self, cw):
  74. titleName = self.title_name()
  75. if titleName.endswith('Equals'):
  76. titleName = titleName[:-1]
  77. cw.writeline("pyOp[\"__%s__\"] = PythonOperationKind.%s;" % (self.name, titleName))
  78. if self.isCompare(): return
  79. cw.writeline("pyOp[\"__r%s__\"] = PythonOperationKind.Reverse%s;" % (self.name, titleName))
  80. cw.writeline("pyOp[\"__i%s__\"] = PythonOperationKind.InPlace%s;" % (self.name, titleName))
  81. def genOperatorReversal_Forward(self, cw):
  82. if self.isCompare(): return
  83. cw.writeline("case Operators.%s: return Operators.Reverse%s;" % (self.title_name(), self.title_name()))
  84. def genOperatorReversal_Reverse(self, cw):
  85. if self.isCompare(): return
  86. cw.writeline("case Operators.Reverse%s: return Operators.%s;" % (self.title_name(), self.title_name()))
  87. def genOperatorTable_Normal(self, cw):
  88. cw.writeline("///<summary>Operator for performing %s</summary>" % self.name)
  89. cw.writeline("%s," % (self.title_name()))
  90. def genOperatorTable_Reverse(self, cw):
  91. if self.isCompare(): return
  92. cw.writeline("///<summary>Operator for performing reverse %s</summary>" % self.name)
  93. cw.writeline("Reverse%s," % (self.title_name()))
  94. def genOperatorTable_InPlace(self, cw):
  95. if self.isCompare(): return
  96. cw.writeline("///<summary>Operator for performing in-place %s</summary>" % self.name)
  97. cw.writeline("InPlace%s," % (self.title_name()))
  98. def genOperatorTable_NormalString(self, cw):
  99. cw.writeline("///<summary>Operator for performing %s</summary>" % self.name)
  100. titleName = self.title_name()
  101. if titleName.endswith('Equals'):
  102. titleName = titleName[:-1]
  103. cw.writeline('public const string %s = "%s";' % (titleName, titleName))
  104. def genOperatorTable_InPlaceString(self, cw):
  105. if self.isCompare(): return
  106. cw.writeline("///<summary>Operator for performing in-place %s</summary>" % self.name)
  107. cw.writeline('public const string InPlace%s = "InPlace%s";' % (self.title_name(), self.title_name()))
  108. def genOperatorToSymbol(self, cw):
  109. cw.writeline("case Operators.%s: return \"__%s__\";" % (self.title_name(), self.name))
  110. if self.isCompare(): return
  111. cw.writeline("case Operators.Reverse%s: return \"__r%s__\";" % (self.title_name(), self.name))
  112. cw.writeline("case Operators.InPlace%s: return \"__i%s__\";" % (self.title_name(), self.name))
  113. def genStringOperatorToSymbol(self, cw):
  114. titleName = self.title_name()
  115. if titleName.endswith('Equals'):
  116. titleName = titleName[:-1]
  117. cw.writeline("case PythonOperationKind.%s: return \"__%s__\";" % (titleName, self.name))
  118. if self.isCompare(): return
  119. cw.writeline("case PythonOperationKind.Reverse%s: return \"__r%s__\";" % (titleName, self.name))
  120. cw.writeline("case PythonOperationKind.InPlace%s: return \"__i%s__\";" % (titleName, self.name))
  121. def genOldStyleOp(self, cw):
  122. if self.isCompare(): return
  123. cw.writeline('[return: MaybeNotImplemented]')
  124. if self.dotnetOp:
  125. cw.enter_block("public static object operator %s([NotNull]OldInstance self, object other)" % self.symbol)
  126. else:
  127. cw.writeline('[SpecialName]')
  128. cw.enter_block("public static object %s([NotNull]OldInstance self, object other)" % self.title_name())
  129. cw.writeline('object res = InvokeOne(self, other, \"__%s__\");' % self.name)
  130. cw.writeline('if (res != NotImplementedType.Value) return res;')
  131. cw.writeline()
  132. cw.writeline("OldInstance otherOc = other as OldInstance;")
  133. cw.enter_block("if (otherOc != null)")
  134. cw.writeline('return InvokeOne(otherOc, self, \"__r%s__\");' % self.name)
  135. cw.exit_block() # end of otherOc != null
  136. cw.writeline("return NotImplementedType.Value;")
  137. cw.exit_block() # end method
  138. cw.writeline()
  139. cw.writeline('[return: MaybeNotImplemented]')
  140. if self.dotnetOp:
  141. cw.enter_block("public static object operator %s(object other, [NotNull]OldInstance self)" % self.symbol)
  142. else:
  143. cw.writeline('[SpecialName]')
  144. cw.enter_block("public static object %s(object other, [NotNull]OldInstance self)" % self.title_name())
  145. cw.writeline("return InvokeOne(self, other, \"__r%s__\");" % self.name)
  146. cw.exit_block() # end method
  147. cw.writeline()
  148. cw.writeline('[return: MaybeNotImplemented]')
  149. cw.writeline('[SpecialName]')
  150. cw.enter_block("public object InPlace%s(object other)" % self.title_name())
  151. cw.writeline("return InvokeOne(this, other, \"__i%s__\");" % self.name)
  152. cw.exit_block() # end method
  153. cw.writeline()
  154. def genWeakRefOperatorNames(self, cw):
  155. cw.writeline('[SlotField] public static PythonTypeSlot __%s__ = new SlotWrapper(\"__%s__\", ProxyType);' % (self.name, self.name))
  156. if self.isCompare(): return
  157. cw.writeline('[SlotField] public static PythonTypeSlot __r%s__ = new SlotWrapper(\"__r%s__\", ProxyType);' % (self.name, self.name))
  158. cw.writeline('[SlotField] public static PythonTypeSlot __i%s__ = new SlotWrapper(\"__i%s__\", ProxyType);' % (self.name, self.name))
  159. def genWeakRefCallableProxyOperatorNames(self, cw):
  160. cw.writeline('[SlotField] public static PythonTypeSlot __%s__ = new SlotWrapper(\"__%s__\", CallableProxyType);' % (self.name, self.name))
  161. if self.isCompare(): return
  162. cw.writeline('[SlotField] public static PythonTypeSlot __r%s__ = new SlotWrapper(\"__r%s__\", CallableProxyType);' % (self.name, self.name))
  163. cw.writeline('[SlotField] public static PythonTypeSlot __i%s__ = new SlotWrapper(\"__i%s__\", CallableProxyType);' % (self.name, self.name))
  164. def genConstantFolding(self, cw, type):
  165. # Exclude bitwise ops on Double and Complex, and exclude comparisons
  166. # on Complex. Also exclude Complex floordiv and because they need to
  167. # issue warnings during runtime.
  168. if type == 'Complex' and (self.clrName in ['Mod', 'FloorDivide']):
  169. return
  170. if self.isCompare():
  171. if type != 'Complex' and self.symbol != '<>':
  172. cw.writeline('case PythonOperator.%s: return new ConstantExpression(ScriptingRuntimeHelpers.BooleanToObject(%sOps.Compare((%s)constLeft.Value, (%s)constRight.Value) %s 0));' % (self.clrName, type, type, type, self.symbol))
  173. elif (type !='Double' and type != 'Complex') or not self.is_bitwise():
  174. cw.writeline('case PythonOperator.%s: return new ConstantExpression(%sOps.%s((%s)constLeft.Value, (%s)constRight.Value));' % (self.clrName, type, self.clrName, type, type))
  175. class Grouping(Symbol):
  176. def __init__(self, symbol, name, side, titleName=None):
  177. Symbol.__init__(self, symbol, side+" "+name, titleName)
  178. self.base_name = name
  179. self.side = side
  180. ops = []
  181. """
  182. 0 expr: xor_expr ('|' xor_expr)*
  183. 1 xor_expr: and_expr ('^' and_expr)*
  184. 2 and_expr: shift_expr ('&' shift_expr)*
  185. 3 shift_expr: arith_expr (('<<'|'>>') arith_expr)*
  186. 4 arith_expr: term (('+'|'-') term)*
  187. 5 term: factor (('*'|'/'|'%'|'//') factor)*
  188. """
  189. # op, pyname, prec, .NET name, .NET op op, pyname, prec, .NET name, .NET op overload
  190. binaries = [('+', 'add', 4, 'Add', True), ('-', 'sub', 4, 'Subtract', True),
  191. ('**', 'pow', 6, 'Power', False), ('*', 'mul', 5, 'Multiply', True),
  192. ('//', 'floordiv', 5, 'FloorDivide', False), ('/', 'div', 5, 'Divide', True),
  193. ('/', 'truediv', 5, 'TrueDivide', False), ('%', 'mod', 5, 'Mod', True),
  194. ('<<', 'lshift', 3, 'LeftShift', False), ('>>', 'rshift', 3, 'RightShift', False),
  195. ('&', 'and', 2, 'BitwiseAnd', True), ('|', 'or', 0, 'BitwiseOr', True),
  196. ('^', 'xor', 1, 'ExclusiveOr', True)]
  197. def add_binaries(list):
  198. for sym, name, prec,clrName, netOp in list:
  199. ops.append(Operator(sym, name, 'r'+name, clrName, prec, dotnetOp = netOp))
  200. ops.append(Symbol(sym+"=", name+" Equal", clrName+ "Equal"))
  201. add_binaries(binaries)
  202. compares = [('<', 'lt', 'ge', 'LessThan', 'GreaterThan', "false", "true", "false"),
  203. ('>', 'gt', 'le', 'GreaterThan', 'LessThan', "false", "false", "true"),
  204. ('<=', 'le', 'gt', 'LessThanOrEqual', 'GreaterThanOrEqual', "true", "true", "false"),
  205. ('>=', 'ge', 'lt', 'GreaterThanOrEqual', 'LessThanOrEqual', "true", "false", "true"),
  206. ('==', 'eq', 'eq', 'Equals', 'NotEquals', 'a', 'a', 'a'),
  207. ('!=', 'ne', 'ne', 'NotEquals', 'Equals', 'a', 'a', 'a'),
  208. ('<>', 'lg', 'lg', 'LessThanGreaterThan', 'Equals', 'a', 'a', 'a')]
  209. for sym, name, rname,clrName,opposite, bool1, bool2, bool3 in compares:
  210. ops.append(Operator(sym, name, rname,clrName, opposite=opposite, bool1=bool1, bool2=bool2, bool3=bool3))
  211. groupings = [('(', ')', 'Paren', 'Parenthesis'), ('[', ']', 'Bracket', 'Bracket'), ('{', '}', 'Brace', 'Brace')]
  212. for sym, rsym, name, fullName in groupings:
  213. ops.append(Grouping(sym, name, 'l', 'Left' + fullName))
  214. ops.append(Grouping(rsym, name, 'r', 'Right' + fullName))
  215. simple = [(',', 'comma'), (':', 'colon'), ('`', 'backquote', 'BackQuote'), (';', 'semicolon'),
  216. ('=', 'assign'), ('~', 'twiddle'), ('@', 'at')]
  217. for info in simple:
  218. if len(info) == 2:
  219. sym, name = info
  220. title = None
  221. else:
  222. sym, name, title = info
  223. ops.append(Symbol(sym, name, title))
  224. start_symbols = {}
  225. for op in ops:
  226. ss = op.symbol[0]
  227. if not start_symbols.has_key(ss): start_symbols[ss] = []
  228. start_symbols[ss].append(op)
  229. def gen_tests(ops, pos, indent=1):
  230. ret = []
  231. default_match = []
  232. future_matches = {}
  233. for sop in ops:
  234. if len(sop.symbol) == pos:
  235. default_match.append(sop)
  236. elif len(sop.symbol) > pos:
  237. ch = sop.symbol[pos]
  238. if future_matches.has_key(ch):
  239. future_matches[ch].append(sop)
  240. else:
  241. future_matches[ch] = [sop]
  242. #assert len(default_match) <= 1
  243. for ch, sops in future_matches.items():
  244. ret.append("if (NextChar('%s')) {" % ch)
  245. ret.extend(gen_tests(sops, pos+1))
  246. ret.append("}")
  247. if default_match:
  248. op = default_match[0]
  249. if isinstance(op, Grouping):
  250. if op.side == 'l':
  251. ret.append("_state.%sLevel++;" % op.base_name);
  252. else:
  253. ret.append("_state.%sLevel--;" % op.base_name);
  254. ret.append("return Tokens.%sToken;" %
  255. op.title_name())
  256. else:
  257. ret.append("return BadChar(ch);")
  258. return [" "*indent + l for l in ret]
  259. def tokenize_generator(cw):
  260. ret = []
  261. done = {}
  262. for op in ops:
  263. ch = op.symbol[0]
  264. if done.has_key(ch): continue
  265. sops = start_symbols[ch]
  266. cw.write("case '%s':" % ch)
  267. for t in gen_tests(sops, 1):
  268. cw.write(t)
  269. done[ch] = True
  270. return ret
  271. friendlyOverload = {'elif':"ElseIf"}
  272. def keywordToFriendly(kw):
  273. if friendlyOverload.has_key(kw):
  274. return friendlyOverload[kw]
  275. return kw.title()
  276. class unique_checker:
  277. def __init__(self):
  278. self.__unique = {}
  279. def unique(self, op):
  280. if not op.symbol in self.__unique:
  281. self.__unique[op.symbol] = op
  282. return True
  283. else: return False
  284. def tokenkinds_generator(cw):
  285. i = 32
  286. uc = unique_checker()
  287. for op in ops:
  288. if not uc.unique(op): continue
  289. cw.write("%s = %d," % (op.title_name(), i))
  290. i += 1
  291. cw.writeline()
  292. keyword_list = list(kwlist)
  293. cw.write("FirstKeyword = Keyword%s," % keywordToFriendly(keyword_list[0]));
  294. cw.write("LastKeyword = Keyword%s," % keywordToFriendly(keyword_list[len(keyword_list) - 1]));
  295. for kw in keyword_list:
  296. cw.write("Keyword%s = %d," % (keywordToFriendly(kw), i))
  297. i += 1
  298. def gen_mark_end(cw, keyword):
  299. if keyword == 'print': cw.enter_block('if (!_printFunction)')
  300. cw.write('MarkTokenEnd();')
  301. if keyword == 'None':
  302. cw.write('return Tokens.NoneToken;')
  303. else:
  304. cw.write('return Tokens.Keyword%sToken;' % keywordToFriendly(keyword))
  305. cw.exit_block()
  306. if keyword == 'print': cw.exit_block()
  307. def gen_token_tree(cw, tree, keyword):
  308. cw.write('ch = NextChar();')
  309. for i, (k, (v, end)) in enumerate(tree.iteritems()):
  310. if i == 0:
  311. cw.enter_block("if (ch == '%c')" % k)
  312. else:
  313. cw.else_block("if (ch == '%c')" % k)
  314. if end and v:
  315. cw.enter_block('if (!IsNamePart(Peek()))')
  316. gen_mark_end(cw, keyword + k)
  317. if not v:
  318. cw.enter_block('if (!IsNamePart(Peek()))')
  319. gen_mark_end(cw, keyword + k)
  320. else:
  321. cur_tree = v
  322. word = []
  323. while True:
  324. if not cur_tree:
  325. cw.enter_block("if (" + ' && '.join(["NextChar() == '%c'" % letter for letter in word]) + ' && !IsNamePart(Peek()))')
  326. gen_mark_end(cw, keyword + k + ''.join(word))
  327. break
  328. elif len(cur_tree) == 1:
  329. word.append(cur_tree.keys()[0])
  330. cur_tree = cur_tree.values()[0][0]
  331. else:
  332. gen_token_tree(cw, v, keyword + k)
  333. break
  334. cw.exit_block()
  335. def keyword_lookup_generator(cw):
  336. cw.write('int ch;')
  337. cw.write('BufferBack();')
  338. keyword_list = list(kwlist)
  339. keyword_list.append('None')
  340. keyword_list.sort()
  341. tree = {}
  342. for kw in keyword_list:
  343. prev = cur = tree
  344. for letter in kw:
  345. val = cur.get(letter)
  346. if val is None:
  347. val = cur[letter] = ({}, False)
  348. prev = cur
  349. cur = val[0]
  350. prev[kw[-1:]] = (cur, True)
  351. gen_token_tree(cw, tree, '')
  352. return
  353. def tokens_generator(cw):
  354. uc = unique_checker()
  355. for op in ops:
  356. if not uc.unique(op): continue
  357. if isinstance(op, Operator) and op.name != "lg":
  358. creator = 'new OperatorToken(TokenKind.%s, "%s", %d)' % (
  359. op.title_name(), op.symbol, op.prec)
  360. else:
  361. creator = 'new SymbolToken(TokenKind.%s, "%s")' % (
  362. op.title_name(), op.symbol)
  363. cw.write("private static readonly Token sym%sToken = %s;" %
  364. (op.title_name(), creator))
  365. cw.writeline()
  366. uc = unique_checker()
  367. for op in ops:
  368. if not uc.unique(op): continue
  369. cw.enter_block("public static Token %sToken" % op.title_name())
  370. cw.write("get { return sym%sToken; }" % op.title_name())
  371. cw.exit_block()
  372. cw.write("")
  373. keyword_list = list(kwlist)
  374. keyword_list.sort()
  375. for kw in keyword_list:
  376. creator = 'new SymbolToken(TokenKind.Keyword%s, "%s")' % (
  377. keywordToFriendly(kw), kw)
  378. cw.write("private static readonly Token kw%sToken = %s;" %
  379. (keywordToFriendly(kw), creator))
  380. cw.write("")
  381. cw.write("")
  382. for kw in keyword_list:
  383. cw.enter_block("public static Token Keyword%sToken" % keywordToFriendly(kw))
  384. cw.write("get { return kw%sToken; }" % keywordToFriendly(kw))
  385. cw.exit_block()
  386. cw.write("")
  387. cw.write("")
  388. UBINOP = """
  389. public static object %(name)s(object x, object y) {
  390. throw new NotImplementedException("%(name)s");
  391. }
  392. """
  393. ADD_EXTRA_VARS = """ string sx, sy;
  394. ExtensibleString es = null;
  395. """
  396. ADD_EXTRA_EARLY = """ } else if ((sx = x as string) != null && ((sy = y as string) != null || (es = y as ExtensibleString) != null)) {
  397. if (sy != null) return sx + sy;
  398. return sx + es.Value;"""
  399. ADD_EXTRA = """
  400. ISequence seq = x as ISequence;
  401. if (seq != null) { return seq.AddSequence(y); }
  402. """
  403. INPLACE_ADD_EXTRA = """
  404. if (x is string && y is string) {
  405. return ((string)x) + ((string)y);
  406. }
  407. if (x is ReflectedEvent.EventTarget) {
  408. return ((ReflectedEvent.EventTarget)x).InPlaceAdd(y);
  409. }
  410. """
  411. MUL_EXTRA = """
  412. if (x is ISequence) {
  413. return ((ISequence)x).MultiplySequence(y);
  414. } else if (y is ISequence) {
  415. return ((ISequence)y).MultiplySequence(x);
  416. }
  417. """
  418. def gen_OperatorTable(cw):
  419. for op in ops:
  420. if not isinstance(op, Operator): continue
  421. op.genOperatorTable_Normal(cw)
  422. for op in ops:
  423. if not isinstance(op, Operator): continue
  424. op.genOperatorTable_InPlace(cw)
  425. for op in ops:
  426. if not isinstance(op, Operator): continue
  427. op.genOperatorTable_Reverse(cw)
  428. def gen_OperatorStringTable(cw):
  429. for op in ops:
  430. if not isinstance(op, Operator): continue
  431. op.genOperatorTable_NormalString(cw)
  432. for op in ops:
  433. if not isinstance(op, Operator): continue
  434. op.genOperatorTable_InPlaceString(cw)
  435. def gen_operatorMapping(cw):
  436. for op in ops:
  437. if isinstance(op, Operator): op.genOperatorTable_Mapping(cw)
  438. def gen_OperatorToSymbol(cw):
  439. for op in ops:
  440. if not isinstance(op, Operator): continue
  441. op.genOperatorToSymbol(cw)
  442. def gen_StringOperatorToSymbol(cw):
  443. for op in ops:
  444. if not isinstance(op, Operator): continue
  445. op.genStringOperatorToSymbol(cw)
  446. def weakref_operators(cw):
  447. for op in ops:
  448. if not isinstance(op, Operator): continue
  449. if op.is_comparison(): continue
  450. op.genWeakRefOperatorNames(cw)
  451. def weakrefCallabelProxy_operators(cw):
  452. for op in ops:
  453. if not isinstance(op, Operator): continue
  454. if op.is_comparison(): continue
  455. op.genWeakRefCallableProxyOperatorNames(cw)
  456. def oldinstance_operators(cw):
  457. for op in ops:
  458. if not isinstance(op, Operator): continue
  459. op.genOldStyleOp(cw)
  460. def operator_reversal(cw):
  461. for op in ops:
  462. if not isinstance(op, Operator): continue
  463. op.genOperatorReversal_Forward(cw)
  464. op.genOperatorReversal_Reverse(cw)
  465. def fast_op_ret_bool_chooser(cw):
  466. for curType in ('int', ):
  467. cw.enter_block('if (CompilerHelpers.GetType(args[0]) == typeof(%s) && CompilerHelpers.GetType(args[1]) == typeof(%s))' % (curType, curType))
  468. _else = ''
  469. for x in (curType, 'object'):
  470. for y in (curType, 'object'):
  471. cw.enter_block('%sif (typeof(T) == typeof(Func<CallSite, %s, %s, bool>))' % (_else, x, y))
  472. cw.write('res = (T)(object)Get%s%s%sDelegate(opBinder);' % (curType.title(), x.title(), y.title()))
  473. cw.exit_block()
  474. _else = 'else '
  475. cw.exit_block()
  476. def fast_op_ret_bool(cw):
  477. """public bool IntEqualRetBool(CallSite site, object self, object other) {
  478. if (self != null && self.GetType() == typeof(int) &&
  479. other != null && other.GetType() == typeof(int)) {
  480. return (int)self == (int)other;
  481. }
  482. return ((CallSite<Func<CallSite, object, object, bool>>)site).Update(site, self, other);
  483. }"""
  484. for curPyType, curPascalType in (('int', 'Int'), ):
  485. for x in ('object', curPyType):
  486. for y in ('object', curPyType):
  487. cw.enter_block('private Func<CallSite, %s, %s, bool> Get%s%s%sDelegate(BinaryOperationBinder opBinder)' % (x, y, curPascalType, x.title(), y.title()))
  488. cw.enter_block('switch (opBinder.Operation)')
  489. cw.write('case ExpressionType.Equal: return %sEqualRetBool;' % (curPascalType, ))
  490. cw.write('case ExpressionType.NotEqual: return %sNotEqualRetBool; ' % (curPascalType, ))
  491. cw.write('case ExpressionType.GreaterThan: return %sGreaterThanRetBool;' % (curPascalType, ))
  492. cw.write('case ExpressionType.LessThan: return %sLessThanRetBool;' % (curPascalType, ))
  493. cw.write('case ExpressionType.GreaterThanOrEqual: return %sGreaterThanOrEqualRetBool;' % (curPascalType, ))
  494. cw.write('case ExpressionType.LessThanOrEqual:return %sLessThanOrEqualRetBool;' % (curPascalType, ))
  495. cw.exit_block()
  496. cw.write('return null;')
  497. cw.exit_block()
  498. cw.write('')
  499. for op in (('==', 'Equal'), ('!=', 'NotEqual'), ('>', 'GreaterThan'), ('<', 'LessThan'), ('>=', 'GreaterThanOrEqual'), ('<=', 'LessThanOrEqual')):
  500. cw.enter_block('public bool %s%sRetBool(CallSite site, %s self, %s other)' % (curPascalType, op[1], x, y))
  501. if x == 'object':
  502. cw.enter_block('if (self != null && self.GetType() == typeof(%s))' % curPyType)
  503. if y == 'object':
  504. cw.enter_block('if (other != null && other.GetType() == typeof(%s))' % curPyType)
  505. cw.write('return (%s)self %s (%s)other;' % (curPyType, op[0], curPyType))
  506. if x == 'object':
  507. cw.exit_block()
  508. if y == 'object':
  509. cw.exit_block()
  510. if x == 'object' or y == 'object':
  511. cw.write('return ((CallSite<Func<CallSite, %s, %s, bool>>)site).Update(site, self, other);' % (x, y))
  512. cw.exit_block()
  513. cw.write('')
  514. def gen_constant_folding(cw):
  515. types = ['Int32', 'Double', 'BigInteger', 'Complex']
  516. for cur_type in types:
  517. cw.enter_block('if (constLeft.Value.GetType() == typeof(%s))' % (cur_type, ))
  518. cw.enter_block('switch (_op)')
  519. for op in ops:
  520. gen = getattr(op, 'genConstantFolding', None)
  521. if gen is not None:
  522. gen(cw, cur_type)
  523. cw.exit_block()
  524. cw.exit_block()
  525. def main():
  526. return generate(
  527. ("Python Keyword Lookup", keyword_lookup_generator),
  528. ("Python Constant Folding", gen_constant_folding),
  529. ("Python Fast Ops RetBool Chooser", fast_op_ret_bool_chooser),
  530. ("Python Fast Ops Ret Bool", fast_op_ret_bool),
  531. ("Tokenize Ops", tokenize_generator),
  532. ("Token Kinds", tokenkinds_generator),
  533. ("Tokens", tokens_generator),
  534. ("Table of Operators", gen_OperatorTable),
  535. ("PythonOperator Mapping", gen_operatorMapping),
  536. #("OperatorToSymbol", gen_OperatorToSymbol),
  537. ("StringOperatorToSymbol", gen_StringOperatorToSymbol),
  538. ("WeakRef Operators Initialization", weakref_operators),
  539. ("OldInstance Operators", oldinstance_operators),
  540. #("Operator Reversal", operator_reversal),
  541. ("WeakRef Callable Proxy Operators Initialization", weakrefCallabelProxy_operators),
  542. )
  543. if __name__ == "__main__":
  544. main()