aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/expressions.h
diff options
context:
space:
mode:
authorRobin Haberkorn <rhaberkorn@fmsbw.de>2026-10-31 13:46:11 +0100
committerRobin Haberkorn <rhaberkorn@fmsbw.de>2026-10-31 21:13:19 +0100
commit4aa2b717f9e050783b567540d9bb0193d692e3e9 (patch)
tree39b3734c464655e6d1c21390945209a66f952654 /src/expressions.h
parente0bf13622b0922252439e3fa8b43df9877678d75 (diff)
support floating point numbers
* Extends the SciTECO type system. A number on the expression stack or in a Q-register can be either an integer or a float. * Floating point constants begin with a digit (like all other numbers), are followed by a `.` and an optional fractional part. Exponents cannot currently be written. E.g. `1.` == `1.0`. But `.0` would still be `.,0`. (!) To push an integer followed by dot, you must now write e.g. `1,.` or `1 .`. * All of the basic arithmetic operators operate like this: If both operands are integers, the result is also an integer (integer arithmetics). If at least one of the operands is a float, the result is also a float (float arithmetics). * All of the binary operators (AND, OR, XOR) always cast all operands to integer and the result is always an integer as well. * You can "cast" integers to float by `*1.` or `/1.`. You can "cast" floats to integers using `#0`. * Most commands still accept only integers. Floats are implicitly casted to integers. Float-aware commands are: =, \, ^W, Qq, Uq, %q and the conditionals. * `%q` will not change the current type of register q. * Numeric part of "lexer.font" is now a float (in points). * You cannot currently print octal and hexadecimal floats. `==` and `===` are identical to `=` on floats. * `===` is now printing hex integers in lower case. This is because SciTECO's coding style for hex constants is also lower case. * `--with-teco-integer` renamed to `--with-teco-number`.
Diffstat (limited to 'src/expressions.h')
-rw-r--r--src/expressions.h76
1 files changed, 65 insertions, 11 deletions
diff --git a/src/expressions.h b/src/expressions.h
index 37aef70..1c1b4e9 100644
--- a/src/expressions.h
+++ b/src/expressions.h
@@ -79,7 +79,8 @@ typedef enum {
TECO_OP_NIL = 0x00,
TECO_OP_NEW,
TECO_OP_BRACE,
- TECO_OP_NUMBER,
+ TECO_OP_INTEGER,
+ TECO_OP_FLOAT,
/*
* Real operators
*/
@@ -102,7 +103,23 @@ teco_set_num_sign(gint sign)
teco_undo_gint(teco_num_sign) = sign;
}
-void teco_expressions_push_int(teco_int_t number);
+teco_operator_t teco_expressions_peek_op(guint index);
+teco_operator_t teco_expressions_pop_op(guint index);
+void teco_expressions_push_op(teco_operator_t op);
+
+void teco_expressions_push_num(teco_number_t number, gboolean is_float);
+
+static inline void
+teco_expressions_push_int(teco_int_t number)
+{
+ teco_expressions_push_num((teco_number_t){.i = number}, FALSE);
+}
+
+static inline void
+teco_expressions_push_float(teco_float_t number)
+{
+ teco_expressions_push_num((teco_number_t){.f = number}, TRUE);
+}
/** Push characters of a C-string. */
static inline void
@@ -112,11 +129,46 @@ teco_expressions_push_str(const gchar *str)
teco_expressions_push_int(*str++);
}
-teco_int_t teco_expressions_peek_num(guint index);
-teco_int_t teco_expressions_pop_num(guint index);
-gboolean teco_expressions_pop_num_calc(teco_int_t *ret, teco_int_t imply, GError **error);
+teco_number_t teco_expressions_peek_num(guint index);
+
+static inline teco_int_t
+teco_expressions_peek_int(guint index)
+{
+ teco_number_t number = teco_expressions_peek_num(index);
+ return teco_expressions_peek_op(index) == TECO_OP_FLOAT ? (teco_int_t)number.f : number.i;
+}
+
+teco_number_t teco_expressions_pop_num(guint index, gboolean *is_float);
+
+static inline teco_int_t
+teco_expressions_pop_int(guint index)
+{
+ gboolean is_float;
+ teco_number_t number = teco_expressions_pop_num(index, &is_float);
+ return is_float ? (teco_int_t)number.f : number.i;
+}
+
+gboolean teco_expressions_pop_num_calc(teco_number_t *ret, gboolean *is_float,
+ teco_int_t imply, GError **error);
+
+/**
+ * Pop an integer from the number stack.
+ *
+ * This automatically casts floats to integers.
+ *
+ * @see teco_expressions_pop_num_calc
+ */
+static inline gboolean
+teco_expressions_pop_int_calc(teco_int_t *ret, teco_int_t imply, GError **error)
+{
+ teco_number_t number;
+ gboolean is_float;
+ if (!teco_expressions_pop_num_calc(&number, &is_float, imply, error))
+ return FALSE;
+ *ret = is_float ? (teco_int_t)number.f : number.i;
+ return TRUE;
+}
-void teco_expressions_push_op(teco_operator_t op);
gboolean teco_expressions_push_calc(teco_operator_t op, GError **error);
/*
@@ -124,12 +176,10 @@ gboolean teco_expressions_push_calc(teco_operator_t op, GError **error);
*/
#define teco_expressions_push(X) \
(_Generic((X), default : teco_expressions_push_int, \
+ teco_float_t : teco_expressions_push_float, \
char * : teco_expressions_push_str, \
const char * : teco_expressions_push_str)(X))
-teco_operator_t teco_expressions_peek_op(guint index);
-teco_operator_t teco_expressions_pop_op(guint index);
-
gboolean teco_expressions_eval(gboolean pop_brace, GError **error);
guint teco_expressions_args(void);
@@ -146,8 +196,12 @@ gboolean teco_expressions_brace_close(GError **error);
void teco_expressions_clear(void);
-/** Maximum size required to format a number if radix == 2 */
+/**
+ * Maximum size required to format a teco_int_t if radix == 2.
+ * It's also sufficient for formatting a teco_float_t.
+ */
#define TECO_EXPRESSIONS_FORMAT_LEN \
(1 + sizeof(teco_int_t)*8 + 1)
-gchar *teco_expressions_format(gchar *buffer, teco_int_t number, teco_qreg_t *radix);
+gchar *teco_expressions_format_int(gchar *buffer, teco_int_t number, teco_qreg_t *radix);
+gchar *teco_expressions_format_float(gchar *buffer, teco_float_t number, guint precision);