From 6f8f9fb53b5a7ef26496d496a4b93266c78d6332 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Sun, 17 May 2015 00:52:23 -0700 Subject: 1390 - support non-integer literals Since '3.14159:literal' looks ugly, we'll just say '3.14159'. It's not like non-integers can be confused for anything but literals. Once I tried to turn reagent values into doubles, I uncovered a bug: arithmetic using signed integers is busted; if either operand of subtraction is unsigned the result is unsigned as well. If it needs to be negative: ka-boom. It was only masked because I was eventually storing the result in a long long int, where it was out of range, and so overflowing into the correct signed value. Once I switched to doubles the unsigned value would indeed fit without overflowing. Ka-boom. Yet another reminder that unsigned integers suck. I started using them mostly to avoid warnings in loops when comparing with .size(), which is usually a size_t. Who knows what other crap lurks here. Just use signed integers everywhere. (And avoid bitwise operators.) --- 014literal_noninteger.cc | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 014literal_noninteger.cc (limited to '014literal_noninteger.cc') diff --git a/014literal_noninteger.cc b/014literal_noninteger.cc new file mode 100644 index 00000000..94242f41 --- /dev/null +++ b/014literal_noninteger.cc @@ -0,0 +1,33 @@ +//: Support literal non-integers. +//: '3.14159:literal' is ugly, so we'll just say '3.14159' for non-integers. + +:(scenarios load) +:(scenario noninteger_literal) +recipe main [ + 1:number <- copy 3.14159 +] ++parse: ingredient: {name: "3.14159", value: 3.14159, type: 0, properties: ["3.14159": "literal-number"]} + +:(after "reagent::reagent(string s)") + if (is_noninteger(s)) { + name = s; + types.push_back(0); + properties.push_back(pair >(name, vector())); + properties.back().second.push_back("literal-number"); + set_value(to_double(s)); + return; + } + +:(code) +bool is_noninteger(const string& s) { + return s.find_first_not_of("0123456789-.") == NOT_FOUND + && s.find('.') != NOT_FOUND; +} + +double to_double(string n) { + char* end = NULL; + // safe because string.c_str() is guaranteed to be null-terminated + double result = strtod(n.c_str(), &end); + assert(*end == '\0'); + return result; +} -- cgit 1.4.1-2-gfad0