SugarCpp is a programming language which compiles to C++11.
It adds lots of syntax sugar in to C++ and is 100% equivalent C++ code.
SugarCpp is still under development. If you have any idea, please open a issue.
Try SugarCpp in your browser: http://curimit.com/project/SugarCpp/
- Indent-based code block.
- Borrow lots of syntax sugar from CoffeeScript.
- Go style defer/finally statement, be able to handle exceptions.
- (Prolog? Haskell? Scala?) style for loop.
- Multiple return values & parallel assignment.
- C# style lambda expression.
- Inline function definition.
- Haskell style infix function.
- Scala style case class.
import "stdio.h"
int main()
printf("Hello world!")
#include "stdio.h"
int main() {
printf("Hello world!");
}
import "stdio.h"
int main()
sum := 0
for i <- 1 to 10
sum = sum + i
printf("sum = %d\n", sum)
#include "stdio.h"
int main() {
auto sum = 0;
for (auto i = 1; i <= 10; ++i) {
sum = sum + i;
}
printf("sum = %d\n", sum);
}
Due to C++11 does not support C# style Finally syntax, it's difficult to guarantee resource be closed or pointer be deleted while exception happens.
SugarCpp provide two syntax: defer/finally
-
defer
is fast, lightweight, the generate C++ code is highly readable. It simply insert code beforereturn
/continue
/break
statements. So when exception happens, the codes decleared bydefer
are not guarantee to be run. -
finally
is little heavier thandefer
. It is behaved just like the finally syntax in C# or Java. It use deconstructor to guarantee when exception happens, the codes decleared byfinally
will still be run.
Notice it has no extra cost and does not handle exceptions.
import "fstream"
using namespace std
void foo()
fout: ofstream("output.txt")
defer fout.close()
fout.write("Hello World!", 12)
if (false)
return
// A more complex example to show the execution order of defer
void bar()
print("1")
defer print("defer1")
if true
print("2")
defer print("defer2")
if true
print("3")
defer print("defer3")
print("4")
return
print("5")
print("6")
return
#include "fstream"
using namespace std;
void foo() {
ofstream fout("output.txt");
fout.write("Hello World!", 12);
if ((false)) {
fout.close();
return;
}
fout.close();
}
void bar() {
print("1");
if (true) {
print("2");
if (true) {
print("3");
print("4");
print("defer3");
print("defer2");
print("defer1");
return;
}
print("5");
print("defer2");
}
print("6");
print("defer1");
return;
}
This syntax behaved like finally
in Java or C# and even easier to use.
import "stdio.h"
"functional"
using namespace std
void test()
x := new int[100]
finally delete(x)
x[0] = 1
// maybe open file failed
// maybe divided by zero
// anyway, an exception occurs
// we want to avoid memory leak
throw(0)
int main()
try
test()
catch x:int
printf("catch: %d\n", x)
#include "stdio.h"
#include "functional"
using namespace std;
void test() {
auto x = new int[100];
class _t_finally_0 {
public:
std::function<void()> finally;
~_t_finally_0() { finally(); }
} _t_finally_0 = { [&]() { delete(x); } };
x[0] = 1;
throw(0);
}
int main() {
try {
test();
} catch (int x) {
printf("catch: %d\n", x);
}
}
import "stdio.h"
"tuple"
using std::tuple
tuple<T, T> sort<T>(a: T, b: T)
return a < b ? (a, b) : (b, a)
int main()
a := 10
b := 1
(a, b) = sort(a, b)
printf("%d %d\n", a, b)
(a, b) = (b, a)
printf("%d %d\n", a, b)
#include "stdio.h"
#include "tuple"
using std::tuple;
template <typename T>
tuple<T, T> sort(T a, T b) {
return a < b ? std::make_tuple(a, b) : std::make_tuple(b, a);
}
int main() {
auto a = 10;
auto b = 1;
std::tie(a, b) = sort(a, b);
printf("%d %d\n", a, b);
std::tie(a, b) = std::make_tuple(b, a);
printf("%d %d\n", a, b);
}
import "stdio.h"
int main()
for i <- 1 to 10, j <- 1 to 10, i + j == 10
printf("%d + %d = %d")
sum := 0
for i <- 10 downto 1 by -1, i != 5, x <- a[i]
sum += x
#include "stdio.h"
int main() {
for (auto i = 1; i <= 10; ++i) {
for (auto j = 1; j <= 10; ++j) {
if (i + j == 10) {
printf("%d + %d = %d");
}
}
}
auto sum = 0;
for (auto i = 10; i >= 1; i = i + -1) {
if (i != 5) {
for (auto x : a[i]) {
sum += x;
}
}
}
}
int main()
// ?= operator
tree->left ?= new Node()
// ? operator
footprints = yeti ? "bear"
int main() {
if (tree->left == nullptr) {
tree->left = new Node();
}
footprints = yeti != nullptr ? yeti : "bear";
}
int main()
a = 1 <= x <= y <= 10
b = 1 < x != 10
int main() {
a = 1 <= x && x <= y && y <= 10;
b = 1 < x && x != 10;
}
[public]
class Point
x, y := 0
void set(x: int, y: int)
@x = x
@y = y
class Point {
public:
auto x = 0;
auto y = 0;
void set(int x, int y) {
this->x = x;
this->y = y;
}
};
import "stdio.h"
"initializer_list"
int main()
// suffix if
printf("haha!") if score > 90
return 0 if score == 0
// suffix while/until
buy() while supply > demand
sell() until supply > demand
// suffix for
a[i] = 0 for i <- 1 to 10, i % 2 == 0
printf("%s\n", food) for food <- ["toast", "cheese", "wine"]
// combine together
a[i] = i if i % 2== 0 for i <- list
#include "stdio.h"
#include "initializer_list"
int main() {
if (score > 90) {
printf("haha!");
}
if (score == 0) {
return 0;
}
while (supply > demand) {
buy();
}
while (!(supply > demand)) {
sell();
}
for (auto i = 1; i <= 10; ++i) {
if (i % 2 == 0) {
a[i] = 0;
}
}
for (auto food : { "toast", "cheese", "wine" }) {
printf("%s\n", food);
}
for (auto i : list) {
if (i % 2 == 0) {
a[i] = i;
}
}
}
grid:int[][] = [
[1, 2, 3]
[4, 5, 6]
[7, 8, 0]
]
list: int[] = [
1, 2, 3
4, 5, 6
7, 8, 9
]
line: int[] = [1, 2, 3]
int grid[][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 0 } };
int list[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int line[] = { 1, 2, 3 };
<tr>
<td>isnt</td>
<td>!=</td>
</tr>
<tr>
<td>and</td>
<td>&&</td>
</tr>
<tr>
<td>or</td>
<td>||</td>
</tr>
SugarCpp | C++ |
---|---|
is | == |
import "stdio.h"
int main()
x := 1
// capture by reference
f := () -> ++x
// capture by value
f := () => ++x
#include "stdio.h"
int main() {
auto x = 1;
auto f = ([&]() { return ++x; });
auto f = ([=]() { return ++x; });
}
enum Color = RED | GREEN | BLUE
enum Color {
RED = 0,
GREEN,
BLUE
};
// basic syntax
a := 1
a, b : int
// advanced syntax
a, b: int(1)
a, b := 1, 2
a, b := 1
auto a = 1;
int a, b;
int a(1);
int b(1);
auto a = 1;
auto b = 2;
auto a = 1;
auto b = 1;
T max<T>(x: T, y: T) = x > y ? x : y
template <typename T>
T max(T x, T y) {
return x > y ? x : y;
}
class Expr
class Number<T>(value:T): Expr
class ExprBin(op:string, l:Expr, r:Expr): Expr
class Expr {
};
template <typename T>
class Number: public Expr {
public:
T value;
Number(T value) {
this->value = value;
}
inline tuple<T> Unapply() {
return std::make_tuple(value);
}
};
class ExprBin: public Expr {
public:
string op;
Expr l;
Expr r;
ExprBin(string op, Expr l, Expr r) {
this->op = op;
this->l = l;
this->r = r;
}
inline tuple<string, Expr, Expr> Unapply() {
return std::make_tuple(op, l, r);
}
};
import "stdio.h"
"algorithm"
using std::max
int main()
a, b, c := 1, 2, 3
x := a `max` b `max` c
printf("%d\n", x)
#include "stdio.h"
#include "algorithm"
using std::max;
int main() {
auto a = 1;
auto b = 2;
auto c = 3;
auto x = max(max(a, b), c);
printf("%d\n", x);
}
import "stdio.h"
[friend(Print)]
class Test
[public]
Test(x: int) = this->x = x
[private]
x: int
class Print
[public, static]
void print(a :Test&) = printf("%d", a.x)
int main()
a := Test(123)
Print::print(a)
#include "stdio.h"
class Test {
friend class Print;
public:
Test(int x) {
this->x = x;
}
private:
int x;
};
class Print {
public:
static void print(Test& a) {
printf("%d", a.x);
}
};
int main() {
auto a = Test(123);
Print::print(a);
}
[FlagAttribute]
enum MyFlags = None | Flag1 | Flag2 | Flag3 | Flag4
enum MyFlags {
None = 0,
Flag1 = 1,
Flag2 = 2,
Flag3 = 4,
Flag4 = 8
};
import "stdio.h"
[ToString]
enum Day = Sunday | Monday | Tuesday | Wednesday | Thursday | Friday | Saturday
int main()
day := Sunday
name := day:ToString()
printf("%s\n", name)
#include "stdio.h"
enum Day {
Sunday = 0,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
};
const char* ToString(const Day& a) {
switch (a) {
case Sunday:
return "Sunday";
case Monday:
return "Monday";
case Tuesday:
return "Tuesday";
case Wednesday:
return "Wednesday";
case Thursday:
return "Thursday";
case Friday:
return "Friday";
case Saturday:
return "Saturday";
}
}
int main() {
auto day = Sunday;
auto name = ToString(day);
printf("%s\n", name);
}
namespace SugarCpp::AstNode::Expr
class ExprBin
Left, Right : Expr
Op : string
namespace SugarCpp {
namespace AstNode {
namespace Expr {
class ExprBin {
Expr Left, Right;
string Op;
};
}
}
}
typedef u_int32 = unsigned int
typedef unsigned int u_int32;
SugarCpp
Compiler Version 1.0.0
Command Line Interface Version 1.0.2
Project website: https://github.com/curimit/SugarCpp
Usage:
sugarcpp [filename] <options>
sugarcpp compile [filename] <compiler arguments>
sugarcpp run [filename] <arguments>
Options:
--ast /ast Output the abstract syntax tree.
--help -h /help /h /? Output this help text.
--nocode /nocode Do not print the generated code.
--output -o /output /o [filename]
Filename of output. If not specified, output
will be printed to standard output.
--token /token Output the tokens.
Examples:
Translate into C++ code
sugarcpp code.sc -o code.cpp
Compile to binary by calling the default compiler
sugarcpp compule code.sc -o code.exe
Compile and run
sugarcpp run code.sc