Add MPFR type, including default value and serialization/deserialization
authorNick Downing <nick@ndcode.org>
Tue, 5 Dec 2023 01:29:35 +0000 (12:29 +1100)
committerNick Downing <nick@ndcode.org>
Tue, 5 Dec 2023 01:29:40 +0000 (12:29 +1100)
ndcode/pitree/pitree.l
ndcode/pitree/pitree.t
ndcode/pitree/pitree.y

index 01649e9..e167942 100644 (file)
@@ -67,6 +67,7 @@
   "float"                      return y_tab.KEYWORD_FLOAT
   "int"                                return y_tab.KEYWORD_INT
   "list"                       return y_tab.KEYWORD_LIST
+  "mpfr"                       return y_tab.KEYWORD_MPFR
   "ref"                                return y_tab.KEYWORD_REF
   "set"                                return y_tab.KEYWORD_SET
   "str"                                return y_tab.KEYWORD_STR
index 331be65..c54f23c 100644 (file)
 
 %{
   from ndcode.pitree import element
+  import gmpy2
   import sys
+
+  gmpy2.get_context().precision = 128
 %}
 
 %%
@@ -78,6 +81,7 @@ class AST {
   class TypeInt: Type;
   class TypeFloat: Type;
   class TypeList: Type;
+  class TypeMPFR: Type;
   class TypeRef: Type;
   class TypeSet: Type;
   class TypeStr: Type;
@@ -343,7 +347,7 @@ def generate_expression(self, _type):
 @method(AST.LiteralBool)
 def generate_expression(self, _type):
   assert isinstance(_type, AST.TypeBool)
-  return "True" if self.value else "False"
+  return 'True' if self.value else 'False'
 @method(AST.LiteralDict)
 def generate_expression(self, _type):
   assert isinstance(_type, AST.TypeDict)
@@ -364,8 +368,11 @@ def generate_expression(self, _type):
   return str(self.get_value())
 @method(AST.LiteralFloat)
 def generate_expression(self, _type):
-  assert isinstance(_type, AST.TypeFloat)
-  return str(self.get_value())
+  if isinstance(_type, AST.TypeFloat):
+    return str(self.get_value())
+  if isinstance(_type, AST.TypeMPFR):
+    return repr(self.get_value())
+  assert False
 @method(AST.LiteralList)
 def generate_expression(self, _type):
   assert isinstance(_type, AST.TypeList)
@@ -435,8 +442,11 @@ def generate_expression_json(self, _type):
   return self.get_value()
 @method(AST.LiteralFloat)
 def generate_expression_json(self, _type):
-  assert isinstance(_type, AST.TypeFloat)
-  return self.get_value()
+  if isinstance(_type, AST.TypeFloat):
+    return float(self.get_value())
+  if isinstance(_type, AST.TypeMPFR):
+    return str(self.get_value())
+  assert False
 @method(AST.LiteralList)
 def generate_expression_json(self, _type):
   assert isinstance(_type, AST.TypeList)
@@ -524,6 +534,9 @@ def generate_serialize(self, context, expr):
   )
   context.indent = indent_save
   return result
+@method(AST.TypeMPFR)
+def generate_serialize(self, context, expr):
+  return f'str({expr:s})'
 @method(AST.TypeRef)
 def generate_serialize(self, context, expr):
   assert not self.is_json
@@ -608,6 +621,9 @@ def generate_deserialize(self, context, expr):
   )
   context.indent = indent_save
   return result
+@method(AST.TypeMPFR)
+def generate_deserialize(self, context, expr):
+  return f'gmpy2.mpfr({expr:s})'
 @method(AST.TypeRef)
 def generate_deserialize(self, context, expr):
   assert not self.is_json
@@ -641,13 +657,16 @@ del generate_deserialize
 @method(AST.Type)
 def is_mutable(self):
   return True
+@method(AST.TypeBool)
+def is_mutable(self):
+  return False
 @method(AST.TypeInt)
 def is_mutable(self):
   return False
 @method(AST.TypeFloat)
 def is_mutable(self):
   return False
-@method(AST.TypeBool)
+@method(AST.TypeMPFR)
 def is_mutable(self):
   return False
 @method(AST.TypeStr)
@@ -673,6 +692,9 @@ def null_value(self):
 @method(AST.TypeList)
 def null_value(self):
   return '[]'
+@method(AST.TypeMPFR)
+def null_value(self):
+  return 'gmpy2.mpfr(0)'
 @method(AST.TypeRef)
 def null_value(self):
   return 'None'
@@ -716,7 +738,7 @@ def get_value(self):
       exponent = -exponent
   value = (
     int(self.integer_digits + self.fraction_digits) *
-      10. ** (exponent - len(self.fraction_digits))
+      gmpy2.exp10(exponent - len(self.fraction_digits))
   )
   if self.sign == '-':
     value = -value
@@ -764,6 +786,9 @@ def post_process(self):
 def post_process(self):
   self.children[0].post_process()
   self.is_json = self.children[0].is_json
+@method(AST.TypeMPFR)
+def post_process(self):
+  self.is_json = False
 @method(AST.TypeRef)
 def post_process(self):
   self.is_json = False
index fac0116..a1b5768 100644 (file)
@@ -23,7 +23,7 @@
 %}
 
 %token CODEBLOCK_START CODEBLOCK_END SECTION2_START SECTION3_START
-%token KEYWORD_BOOL KEYWORD_CLASS KEYWORD_DICT KEYWORD_INT KEYWORD_FLOAT KEYWORD_LIST
+%token KEYWORD_BOOL KEYWORD_CLASS KEYWORD_DICT KEYWORD_INT KEYWORD_FLOAT KEYWORD_LIST KEYWORD_MPFR
 %token KEYWORD_REF KEYWORD_SET KEYWORD_STR IDENTIFIER LITERAL_BOOL LITERAL_DICT
 %token LITERAL_INT LITERAL_FLOAT LITERAL_REF
 
@@ -69,6 +69,7 @@ type
   | %space (?E{t_def.AST.TypeRef}KEYWORD_REF)
   | %space (?E{t_def.AST.TypeSet}KEYWORD_SET '(' type ')')
   | %space (?E{t_def.AST.TypeStr}KEYWORD_STR)
+  | %space (?E{t_def.AST.TypeMPFR}KEYWORD_MPFR)
   ;
  
 default_value_opt