Skip to main content
added 23 characters in body
Source Link
/*The C++ wrapper around "fibonacci.aec". Compile this as:
    node aec fibonacci.aec #Assuming you've downloaded aec.js from the releases.
    g++ -o fibonacci let_gcc_setup_gas.cpp fibonacci.s
*/
#include <algorithm> //The "fill" function.
#include <cmath>     //The "isnan" function.
#include <iostream>
#ifdef _WIN32
#include <cstdlib> //system("PAUSE");
#endif

extern "C" { // To the GNU Linker (which comes with Linux and is used by GCC),
             // AEC language is a dialect of C, and AEC is a C compiler.
float n, stackWithLocalVariables[1024], memoisation[1024],
    topOfTheStackWithLocalVariables, temporaryResult, returnValue,
    result; // When using GCC, there is no need to declare variables in the same
            // file as you will be using them, or even in the same language. So,
            // no need to look up the hard-to-find information about how to
            // declare variables in GNU Assembler while targeting 64-bit Linux.
            // GCC and GNU Linker will take care of that.
void fibonacci(); // The ".global fibonacci" from inline assembly in
                  // "fibonacci.aec" (you need to declare it, so that the C++
                  // compiler doesn't complain: C++ isn't like JavaScript or AEC
                  // in that regard, C++ tries to catch errors such as a
                  // mistyped function or variable name in compile-time).
}

int main() {
  std::cout << "Enter n:" << std::endl;
  std::cin >> n;
  topOfTheStackWithLocalVariables = -1;
  if (n >= 2)
    std::fill(&memoisation[0], &memoisation[int(n)],
              0); // This is way more easily done in C++ than in AEC here, because
                  // because the AEC subprogram doesn't know if it's being 
 called by C++
                // called by C++ or recursively by itself.
  fibonacci();
  if (std::isnan(returnValue)) {
    std::cerr << "The AEC program returned an invalid decimal number."
              << std::endl;
    return 1;
  }
  std::cout << "The " << n
            << ((int(n) % 10 == 3)
                    ? ("rd")
                    : (int(n) % 10 == 2) ? ("nd")
                                         : (int(n) % 10 == 1) ? ("st") : "th")
            << " Fibonacci number is " << returnValue << "." << std::endl;
#ifdef _WIN32
  std::system("PAUSE");
#endif
  return 0;
}

/*The C++ wrapper around "fibonacci.aec". Compile this as:
    node aec fibonacci.aec #Assuming you've downloaded aec.js from the releases.
    g++ -o fibonacci let_gcc_setup_gas.cpp fibonacci.s
*/
#include <algorithm> //The "fill" function.
#include <cmath>     //The "isnan" function.
#include <iostream>
#ifdef _WIN32
#include <cstdlib> //system("PAUSE");
#endif

extern "C" { // To the GNU Linker (which comes with Linux and is used by GCC),
             // AEC language is a dialect of C, and AEC is a C compiler.
float n, stackWithLocalVariables[1024], memoisation[1024],
    topOfTheStackWithLocalVariables, temporaryResult, returnValue,
    result; // When using GCC, there is no need to declare variables in the same
            // file as you will be using them, or even in the same language. So,
            // no need to look up the hard-to-find information about how to
            // declare variables in GNU Assembler while targeting 64-bit Linux.
            // GCC and GNU Linker will take care of that.
void fibonacci(); // The ".global fibonacci" from inline assembly in
                  // "fibonacci.aec" (you need to declare it, so that the C++
                  // compiler doesn't complain: C++ isn't like JavaScript or AEC
                  // in that regard, C++ tries to catch errors such as a
                  // mistyped function or variable name in compile-time).
}

int main() {
  std::cout << "Enter n:" << std::endl;
  std::cin >> n;
  topOfTheStackWithLocalVariables = -1;
  std::fill(&memoisation[0], &memoisation[int(n)],
            0); // This is way more easily done in C++ than in AEC here, because
                // the AEC subprogram doesn't know if it's being called by C++
                // or recursively by itself.
  fibonacci();
  if (std::isnan(returnValue)) {
    std::cerr << "The AEC program returned an invalid decimal number."
              << std::endl;
    return 1;
  }
  std::cout << "The " << n
            << ((int(n) % 10 == 3)
                    ? ("rd")
                    : (int(n) % 10 == 2) ? ("nd")
                                         : (int(n) % 10 == 1) ? ("st") : "th")
            << " Fibonacci number is " << returnValue << "." << std::endl;
#ifdef _WIN32
  std::system("PAUSE");
#endif
  return 0;
}

/*The C++ wrapper around "fibonacci.aec". Compile this as:
    node aec fibonacci.aec #Assuming you've downloaded aec.js from the releases.
    g++ -o fibonacci let_gcc_setup_gas.cpp fibonacci.s
*/
#include <algorithm> //The "fill" function.
#include <cmath>     //The "isnan" function.
#include <iostream>
#ifdef _WIN32
#include <cstdlib> //system("PAUSE");
#endif

extern "C" { // To the GNU Linker (which comes with Linux and is used by GCC),
             // AEC language is a dialect of C, and AEC is a C compiler.
float n, stackWithLocalVariables[1024], memoisation[1024],
    topOfTheStackWithLocalVariables, temporaryResult, returnValue,
    result; // When using GCC, there is no need to declare variables in the same
            // file as you will be using them, or even in the same language. So,
            // no need to look up the hard-to-find information about how to
            // declare variables in GNU Assembler while targeting 64-bit Linux.
            // GCC and GNU Linker will take care of that.
void fibonacci(); // The ".global fibonacci" from inline assembly in
                  // "fibonacci.aec" (you need to declare it, so that the C++
                  // compiler doesn't complain: C++ isn't like JavaScript or AEC
                  // in that regard, C++ tries to catch errors such as a
                  // mistyped function or variable name in compile-time).
}

int main() {
  std::cout << "Enter n:" << std::endl;
  std::cin >> n;
  topOfTheStackWithLocalVariables = -1;
  if (n >= 2)
    std::fill(&memoisation[0], &memoisation[int(n)],
              0); // This is way more easily done in C++ than in AEC here,
                  // because the AEC subprogram doesn't know if it's being 
                  // called by C++ or recursively by itself.
  fibonacci();
  if (std::isnan(returnValue)) {
    std::cerr << "The AEC program returned an invalid decimal number."
              << std::endl;
    return 1;
  }
  std::cout << "The " << n
            << ((int(n) % 10 == 3)
                    ? ("rd")
                    : (int(n) % 10 == 2) ? ("nd")
                                         : (int(n) % 10 == 1) ? ("st") : "th")
            << " Fibonacci number is " << returnValue << "." << std::endl;
#ifdef _WIN32
  std::system("PAUSE");
#endif
  return 0;
}

added 206 characters in body
Source Link

The executable files for Windows and Linux are available here, and the assembly code that my compiler for AEC generates is available here.
So, what do you think about it?

The executable files for Windows and Linux are available here.
So, what do you think about it?

The executable files for Windows and Linux are available here, and the assembly code that my compiler for AEC generates is available here.
So, what do you think about it?

Source Link

Fibonacci Sequence using Recursion with Memoisation

File fibonacci.aec:

syntax GAS ;We are, of course, targeting GNU Assembler here, rather than FlatAssembler, to be compatible with GCC.
verboseMode on ;Tells ArithmeticExpressionCompiler to output more comments into the assembly code it produces (fibonacci.s).
AsmStart
    .global fibonacci #We need to tell the linker that "fibonacci" is the name of a function, and not some random label.
    fibonacci:
AsmEnd
If not(mod(n,1)=0) ;If 'n' is not a integer, round it to the nearest integer.
    n := n + ( mod(n,1) > 1/2 ? 1-mod(n,1) : (-mod(n,1)))
EndIf
If n<2 ;The 1st Fibonacci number is 1, and the 0th one is 0.
    returnValue := n > -1 ? n : 0/0 ;0/0 is NaN (indicating error), because negative Fibonacci numbers don't exist
    AsmStart
        .intel_syntax noprefix
        ret #Far return (to the other section, that is, to the C++ program). The way to do a same-section return depends on whether we are in a 32-bit Assembler or a 64-bit Assembler, while the far return is the same (at least in the "intel_syntax mode").
        .att_syntax
    AsmEnd
ElseIf not(memoisation[n]=0) ;Has that Fibonacci number already been calculated?
    returnValue:=memoisation[n]
    AsmStart
        .intel_syntax noprefix
        ret
        .att_syntax
    AsmEnd
EndIf
;And now comes the part where we are tricking ArithmeticExpressionCompiler into supporting recursion...
topOfTheStackWithLocalVariables := topOfTheStackWithLocalVariables + 2 ;Allocate space on the stack for 2 local variables ('n', the argument passed to the function, and the temporary result).
temporaryResult := 0 ;The sum of fib(n-1) and fib(n-2) will be stored here, first 0 then fib(n-1) then fib(n-1)+fib(n-2).
stackWithLocalVariables[topOfTheStackWithLocalVariables - 1] := temporaryResult ;Save the local variables onto the stack, for the recursive calls will corrupt them (as they are actually global variables, because ArithmeticExpressionCompiler doesn't support local ones).
stackWithLocalVariables[topOfTheStackWithLocalVariables] := n
n:=n-1
AsmStart
    .intel_syntax noprefix
    call fibonacci
    .att_syntax
AsmEnd
temporaryResult := stackWithLocalVariables[topOfTheStackWithLocalVariables - 1]
temporaryResult := temporaryResult + returnValue ;"returnValue" is supposed to contain fib(n-1).
;And we repeat what we did the last time, now with n-2 instead of n-1...
stackWithLocalVariables[topOfTheStackWithLocalVariables - 1] := temporaryResult
n := stackWithLocalVariables[topOfTheStackWithLocalVariables]
n := n - 2
AsmStart
    .intel_syntax noprefix
    call fibonacci
    .att_syntax
AsmEnd
temporaryResult := stackWithLocalVariables[topOfTheStackWithLocalVariables - 1]
temporaryResult := temporaryResult + returnValue
stackWithLocalVariables[topOfTheStackWithLocalVariables - 1] := temporaryResult
n := stackWithLocalVariables [topOfTheStackWithLocalVariables]
returnValue := temporaryResult
memoisation[n] := returnValue
topOfTheStackWithLocalVariables := topOfTheStackWithLocalVariables - 2
AsmStart
    .intel_syntax noprefix
    ret
    .att_syntax
AsmEnd

File let_gcc_setup_gas.cpp:

/*The C++ wrapper around "fibonacci.aec". Compile this as:
    node aec fibonacci.aec #Assuming you've downloaded aec.js from the releases.
    g++ -o fibonacci let_gcc_setup_gas.cpp fibonacci.s
*/
#include <algorithm> //The "fill" function.
#include <cmath>     //The "isnan" function.
#include <iostream>
#ifdef _WIN32
#include <cstdlib> //system("PAUSE");
#endif

extern "C" { // To the GNU Linker (which comes with Linux and is used by GCC),
             // AEC language is a dialect of C, and AEC is a C compiler.
float n, stackWithLocalVariables[1024], memoisation[1024],
    topOfTheStackWithLocalVariables, temporaryResult, returnValue,
    result; // When using GCC, there is no need to declare variables in the same
            // file as you will be using them, or even in the same language. So,
            // no need to look up the hard-to-find information about how to
            // declare variables in GNU Assembler while targeting 64-bit Linux.
            // GCC and GNU Linker will take care of that.
void fibonacci(); // The ".global fibonacci" from inline assembly in
                  // "fibonacci.aec" (you need to declare it, so that the C++
                  // compiler doesn't complain: C++ isn't like JavaScript or AEC
                  // in that regard, C++ tries to catch errors such as a
                  // mistyped function or variable name in compile-time).
}

int main() {
  std::cout << "Enter n:" << std::endl;
  std::cin >> n;
  topOfTheStackWithLocalVariables = -1;
  std::fill(&memoisation[0], &memoisation[int(n)],
            0); // This is way more easily done in C++ than in AEC here, because
                // the AEC subprogram doesn't know if it's being called by C++
                // or recursively by itself.
  fibonacci();
  if (std::isnan(returnValue)) {
    std::cerr << "The AEC program returned an invalid decimal number."
              << std::endl;
    return 1;
  }
  std::cout << "The " << n
            << ((int(n) % 10 == 3)
                    ? ("rd")
                    : (int(n) % 10 == 2) ? ("nd")
                                         : (int(n) % 10 == 1) ? ("st") : "th")
            << " Fibonacci number is " << returnValue << "." << std::endl;
#ifdef _WIN32
  std::system("PAUSE");
#endif
  return 0;
}

The executable files for Windows and Linux are available here.
So, what do you think about it?