3

I would like to know how to do some lower-level thing in C++ that will allow me to do some "wacky" math operations. Specifically my two questions are:

1) How can I define my own math symbol that the compiler will be able to recognizes in my code. In other words, I'm not looking to parse a string from a user, but rather have the compiler recognize this as a new math operation.

   ex:   3 {+} 4   will actually do 3 – 4  etc.

2) How can I define a custom number from an ASCII symbol. For example, define the symbol # to be recognized by the compiler as 18 (i.e. 00010010 in binary).

   ex:   18 {+} # = 18 - 18 = 0

If possible, I would like to be able to do the above two things at the compiler lever. Solutions in C++, Java, C, Python, and Objective-C are fine. Just let me know what language your solution is in. Thanks! :)

Vladimir
  • 225
  • 1
  • 11
  • 3
    One thing is for sure, this can't be achieved with C++ without ugly macros. – teh internets is made of catz Aug 02 '14 at 23:37
  • 3
    Ugly macros might be just the thing here :) – 500 - Internal Server Error Aug 02 '14 at 23:38
  • 2
    Kinda wonky though, as this will not replace true operator definitions. – teh internets is made of catz Aug 02 '14 at 23:39
  • Thanks for the feedback! How "ugly" will this be? (In other words, ugly-code or ugly-inefficient?) – Vladimir Aug 02 '14 at 23:43
  • 2
    You can, of course, write your own compiler. – Hot Licks Aug 02 '14 at 23:44
  • 1
    C++ only lets you define operators for the operators that work on the basic types. Not make up new ones. – brian beuning Aug 02 '14 at 23:44
  • @HotLicks Haha That would be cool, but probably a lot of work ;) – Vladimir Aug 02 '14 at 23:45
  • 5
    You don't even need to write a compiler; all you really have to do is add a process that reads the file and replaces `{+}` with `-` anywhere it appears prior to building. – ChiefTwoPencils Aug 02 '14 at 23:45
  • 1
    Not clear what you're trying to do here, but you *might* (depending on the specific language/compiler) be able to define variables whose names consist of invisible characters concatenated with, eg, `3`. So even though the actual value was not `3` (but some variable/#define value), it *looks* like it's just `3`. – Hot Licks Aug 02 '14 at 23:47
  • @brianbeuning: Oh I see. Is there no way to make anything like a compiler definition? – Vladimir Aug 02 '14 at 23:47
  • 1
    A pre-processing step as @ChiefTwoPencils suggests is the only way you're going to accomplish what you want (especially for the operators) in any language that doesn't have a true macro system (of which all the languages you listed fall into, their macros are textual replaces) – aruisdante Aug 02 '14 at 23:48
  • @ChiefTwoPencils: Hmm that's a good idea, but I'd prefer to avoid file operations if possible. Thanks though! – Vladimir Aug 02 '14 at 23:49
  • @HotLicks: The invisible character idea might work. I'll have to see how this works though. Any chance you could show me a quick example? – Vladimir Aug 02 '14 at 23:51
  • 1
    @Vladimir Writing a small compiler/interpreter is not *so* complicated, there are a bunch of tutorials on the internet about how to build a simple calculator or similar things with lex & yacc. This way you can define the exact operators and symbols you want, maybe it's worth looking into. – teh internets is made of catz Aug 02 '14 at 23:53
  • @aruisdante: Thanks for the explanation. How would I go about setting-up/writing this pre-processor step? – Vladimir Aug 02 '14 at 23:54
  • 1
    One would have to dig through the possible languages and see which would accept, eg, a "required blank" as a symbol name. – Hot Licks Aug 02 '14 at 23:54
  • @tehinternetsismadeofcatz: Sounds like a reasonable option! I'll look into it if there's no simpler way to do it :) – Vladimir Aug 02 '14 at 23:56
  • 1
    Unfortunately Java slices and dices the Unicode character set pretty finely and probably treats all the [likely suspects](http://en.wikipedia.org/wiki/Whitespace_character) as whitespace. Not sure about C++. – Hot Licks Aug 03 '14 at 00:01
  • 1
    @HotLicks C++ compilers generaly only accepts ASCII. There is probably GCC extensions that deals with non-ASCII but I wouldn't rely on this. – teh internets is made of catz Aug 03 '14 at 00:08
  • 1
    Clang has a pretty good understanding of Unicode characters, so like Java, it will recognise all "whitespace" characters as just whitespaces [subject to bugs, of course - there are quite a lot of different characters to classify, so there may be bugs in there]. I don't know about other C or C++ compilers. – Mats Petersson Aug 03 '14 at 00:09
  • @HotLicks: I see, how about any other languages though? Python maybe? – Vladimir Aug 03 '14 at 00:10
  • @MatsPetersson: Clang is a library, right? Sorry if that's a noob question haha – Vladimir Aug 03 '14 at 00:12
  • 1
    Clang I was referring to is the clang and clang++ compilers, using the LLVM framework, but technically, you can use clang as a set of functions/classes in your own code, as a (set of) library/libraries. – Mats Petersson Aug 03 '14 at 00:15
  • @MatsPetersson: Thanks for the explanation. I usually use MinGW, do you think it supports Clang or Clang++? – Vladimir Aug 03 '14 at 00:17
  • 1
    @Vladimir: MinGW is a GCC based compiler. Clang in my context is a "different compiler", not something that can/is supported by MinGW - I _think_ you could perhaps compile a version of Clang with MinGW. But I'm not sure how that in itself it helpful - it won't solve your problem. – Mats Petersson Aug 03 '14 at 00:37

2 Answers2

2

You can wrap the types into a class, then overload the operators. I came up with a minimal example for "wacky" addition (+ becomes -). But if you want to use PODs you have to use the preprocessor, there is no other way.

#include <iostream>
using namespace std;

template<typename T>
class wacky
{
    T val_;
public:
    wacky(T val = {}): val_(val){};

    // let's define a conversion operator
    template<typename S>
    operator S (){return val_;}

    // we don't need asignment operator and copy ctors

    // stream operators
    friend ostream& operator<<(ostream& os, const wacky& rhs)
    {
        return os << rhs.val_;
    }

    // the += operator
    wacky& operator+=(const wacky& rhs)
    {
        val_ -= rhs.val_; // wacky!
        return *this;
    }

    // and the wacky operator+
    friend wacky operator+(wacky lhs, const wacky& rhs)
    {
        return lhs+=rhs;
    }
};

int main()
{
    wacky<int> a,b;
    a = 10;
    b = 15;

    // a and b behave now like PODs
    // implicit conversions work etc
    double wacky_sum = a + b; 
    cout << wacky_sum << endl; // -5
}
vsoftco
  • 55,410
  • 12
  • 139
  • 252
  • 1
    I think the OP's intention is, however, to have `{+}` be a distinct operation from `+`, which is not possible in a language without true macros. Unless it was always safe to have `{+}` be replaced directly with `-`. – aruisdante Aug 02 '14 at 23:49
  • 1
    @aruisdante yes, you cannot just introduce new symbols without preprocessor – vsoftco Aug 02 '14 at 23:49
  • @vsoftco: Thanks! This looks like a great suggestion. :) Too bad if I can get {+} to work though. I would +1 your post but I don't have enough reputation for it :( – Vladimir Aug 03 '14 at 00:01
  • PS. I have enough rep now so I +1ed you. Thanks for this code it's great! – Vladimir Aug 03 '14 at 00:33
  • @Rapptz: They must have changed the policy. I needed 15 rep to upvote hahaha – Vladimir Aug 03 '14 at 00:52
2

I said in my comment that this would imply macros in C++; if what you want is not much more complicated than what you show, it should do the trick. Defining operators as macros should work for simple find/replace cases, but it may not be well suited for complex expressions and certain symbols.

Off my head, I think what you want is feasible in Haskell by using infix functions as operators, but it may not be straight-forward for a beginner. Take a look at Lyah and search for infixr. You need a basic knowledge of Haskell though.

Edit with Zeta example, you can run it in ghci:

(<+>) = (-) -- operator definition
(<*>) = (/)

answer = 42
answer <+> 12 -- prints 30
answer <*> 7 -- prints 6.0
  • Thanks! I'll look into it, but like you said I need to know Haskell hahaha ;) – Vladimir Aug 03 '14 at 00:05
  • 2
    Unfortunately, `{}` are special symbols and cannot be used for own operators. But you can easily create other operators like `<+>`. – Zeta Aug 03 '14 at 00:06
  • @Zeta: Oh! Really? Cool! <+> might work great! If possible could you show me a quick example? :) – Vladimir Aug 03 '14 at 00:14
  • 1
    @Vladimir: `(<+>) = (-)` (easy, huh?). The ASCII symbol is something completely different. You _can_ create operators with no arguments, but you need to enclose them with parentheses: `(#) = 18` and then `18 <+> (#)`. You can check this stuff at http://tryhaskell.org/, but you need to write it like this: `let (<+>) = (-) in 15 <+> 4`. – Zeta Aug 03 '14 at 00:19
  • @Zeta: Sounds great! If you could write this as an "answer" with a small How-To sample code attached, I'll give you the "This answers my question" check mark :) – Vladimir Aug 03 '14 at 00:24
  • 3
    @Vladimir: Actually, as long as this question is tagged as C++, a Haskell answer would be rather off-topic. Also, Haskell is a pure functional programming language. That's a whole other beast compared to C++, C, Java, Python or Objective-C. It will haunt you. It will twist your brain. Depending on what you're trying to do, it would be a total overkill. – Zeta Aug 03 '14 at 00:31
  • @Zeta: Ooooh I see Thanks for clearing that up. I though you meant I can do (<+>) in c++. My bad – Vladimir Aug 03 '14 at 00:38
  • Too bad I can't do this in c++ – Vladimir Aug 03 '14 at 00:39
  • @tehinternetsismadeofc: How efficient is the code you posted? Will <+> be slower then direct subtraction? In other words, will doing <+> be able to do subtraction directly, or will this function call the subtraction function? – Vladimir Aug 03 '14 at 00:48
  • 1
    @Vladimir This is done at compiler level, and the Haskell compiler is pretty smart so I'd say this is strictly equivalent. – teh internets is made of catz Aug 03 '14 at 10:04