Implement (un)signed_int_value() and float_value() for constructing Value objects...
authorNick Downing <nick@ndcode.org>
Wed, 6 Dec 2023 04:07:36 +0000 (15:07 +1100)
committerNick Downing <nick@ndcode.org>
Wed, 6 Dec 2023 09:22:34 +0000 (20:22 +1100)
ansi_c.t

index c12410e..b8a3ba9 100644 (file)
--- a/ansi_c.t
+++ b/ansi_c.t
@@ -32,6 +32,8 @@
   STORAGE_CLASS_REGISTER = 6
   STORAGE_CLASS_ENUM = 7 # internal value, for enum constant "variables"
 
+  INT_SIZE = 4
+  INT_ALIGN = 4
   POINTER_SIZE = 4
   POINTER_ALIGN = 4
 %}
@@ -465,6 +467,27 @@ integer_suffix_to_type = {
 def factory(tag, *args, **kwargs):
   return tag_to_class[tag](*args, **kwargs)
 
+def signed_int_value(value, width):
+  offset = 1 << (width - 1)
+  mask = (1 << width) - 1
+  return ValueInt(value = ((value + offset) & mask) - offset)
+
+def unsigned_int_value(value, width):
+  mask = (1 << width) - 1
+  return ValueInt(value = value & mask)
+
+width_to_gmpy2_context = {
+  32: gmpy2.ieee(32),
+  64: gmpy2.ieee(64),
+  128: gmpy2.ieee(128)
+}
+def float_value(value, width):
+  return ValueFloat(
+    value = gmpy2.mpfr(
+      gmpy2.mpfr(value, context = width_to_gmpy2_context[width])
+    )
+  )
+
 @method(Declarator)
 def get_name_and_type(self, base_type):
   print(self)
@@ -758,14 +781,19 @@ def calc_value(self):
   if len(exponent_part.children) == 0 else
     exponent_part.children[0].value * int(exponent_part.children[1].text[0])
   )
-  self.value = ValueFloat(
-    value = int(digits0 + digits1) * gmpy2.exp10(exponent - len(digits1))
-  ).cast(self.type)
+  self.value = float_value(
+    int(digits0 + digits1) * gmpy2.exp10(exponent - len(digits1)),
+    self.type.size * 8
+  )
 @method(ExpressionIntegerConstant)
 def calc_value(self):
-  self.value = ValueInt(
-    value = int(self.children[0].text[0], self.base)
-  ).cast(self.type)
+  value = int(self.children[0].text[0], self.base)
+  if isinstance(self.type, TypeIntSigned):
+    self.value = signed_int_value(value, self.type.size * 8)
+  elif isinstance(self.type, TypeIntUnsigned):
+    self.value = signed_int_value(value, self.type.size * 8)
+  else:
+    assert False
 @method(ExpressionCharacterConstant)
 def calc_value(self):
   value = 0
@@ -779,7 +807,7 @@ def calc_value(self):
       value = (value << 8) | (int(i.children[0].text[0], i.base) & 0xff)
     else:
       assert False
-  self.value = ValueInt(value = value).cast(self.type)
+  self.value = signed_int_value(value, INT_SIZE * 8)
 @method(ExpressionStringLiteral)
 def calc_value(self):
   values = []
@@ -793,59 +821,12 @@ def calc_value(self):
     else:
       assert False
   values.append(0)
-  self.value = ValueString(values = values) #.cast(self.type) ???
+  self.value = ValueString(values = values)
 @method(ExpressionAssignment)
 def calc_value(self):
   self.value = self.children[1].value
 del calc_value
 
-@method(Value)
-def cast(self, _type):
-  print(self)
-  raise NotImplementedError()
-@method(ValueFloat)
-def cast(self, _type):
-  width = _type.size * 8
-  if isinstance(_type, TypeFloat):
-    return ValueFloat(
-      value = gmpy2.mpfr(
-        gmpy2.mpfr(self.value, context = gmpy2.ieee(width))
-      )
-    )
-  if isinstance(_type, TypeIntSigned):
-    offset = 1 << (width - 1)
-    mask = (1 << width) - 1
-    return ValueInt(
-      value = ((int(gmpy2.rint_trunc(self.value)) + offset) & mask) - offset
-    )
-  if isinstance(_type, TypeIntUnsigned):
-    mask = (1 << width) - 1
-    return ValueInt(
-      value = int(gmpy2.rint_trunc(self.value)) & mask
-    )
-  assert False
-@method(ValueInt)
-def cast(self, _type):
-  width = _type.size * 8
-  if isinstance(_type, TypeFloat):
-    return ValueFloat(
-      value = gmpy2.mpfr(
-        gmpy2.mpfr(self.value, context = gmpy2.ieee(width))
-      )
-    )
-  if isinstance(_type, TypeIntSigned):
-    offset = 1 << (width - 1)
-    mask = (1 << width) - 1
-    return ValueInt(
-      value = ((self.value + offset) & mask) - offset
-    )
-  if isinstance(_type, TypeIntUnsigned):
-    mask = (1 << width) - 1
-    return ValueInt(
-      value = self.value & mask
-    )
-del cast
-
 @method(Node)
 def post_process(self):
   for i in self.children: