Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-4041-

Help with unambiguous grammar

Name: long long 2012-01-13 22:59

I'm creating yet another fail C-family compiler.
Objectives: simple language, generics, type inference, and unambiguous grammar.
I would like to hear your opinions, any help is very appreciated.

bison parser:
%union {
    char *str;
}

%right '=' "+=" "-=" "*=" "/=" "%=" "~=" "&=" "|=" "^=" "<<=" ">>="
%left ':'
%right '?'
%left '|'
%left '^'
%left '&'
%left "or"
%left "and"
%left "==" "!="
%left '<' "<=" '>' ">="
%left "<<" ">>"
%left '+' '-'
%left '*' '/' '%'
%right "not" '~' PREFIX
%left "++" "--"
%left '['
%left '.'
%right '$'

%token <str> ID INT HEX BIN DOUBLE FLOAT COMPLEX STRING CHAR
%token-table

%%

program:
       | program import
       | program decl
       ;

import: "import" module
      | "import" module "as" identifier
      ;

module: identifier
      | module '.' identifier
      ;

decl: declvar
    | declfunc
    | declstruct
    ;

declvar: "var" identifier
       | "var" identifier '=' expr
       | "def" identifier '=' expr
       ;

declstruct: "def" identifier '{' declattrs '}'
          ;

declattrs: declattr
         | declattrs declattr
         ;

declattr: "var" identifier
        | declfunc
        ;

declfunc: "def" identifier '(' declargs ')' block
        ;

declargs: declarg
        | declargs ',' declarg
        ;

declarg: identifier
       | "var" identifier
       | identifier identifier
       ;

block: '{' '}'
     | '{' stmts '}'
     ;

stmts: stmt
     | block
     | stmts stmt
     | stmts block
     ;

stmt: declvar
    | purestmt
    | identifier ':' purestmt
    ;

purestmt: assign
        | call
        | if
        | for
        | while
        | switch
        | "goto" identifier
        | "return" expr
        ;

assign: lvalue '=' expr
      | lvalue "+=" expr
      | lvalue "-=" expr
      | lvalue "*=" expr
      | lvalue "/=" expr
      | lvalue "%=" expr
      | lvalue "~=" expr
      | lvalue "&=" expr
      | lvalue "|=" expr
      | lvalue "^=" expr
      | lvalue "<<=" expr
      | lvalue ">>=" expr
      | lvalue "++"
      | lvalue "--"
//      | "++" lvalue %prec PREFIX
//      | "--" lvalue %prec PREFIX
      ;

lvalue: identifier
      | lvalue '.' identifier
      | lvalue '[' expr ']'
      | '$' lvalue
      ;

identifier: ID
          ;

expr: literal
    | lvalue
    | assign
    | call
    | '~' expr
    | '@' lvalue
    | '-' expr %prec PREFIX
    | expr '+' expr
    | expr '-' expr
    | expr '*' expr
    | expr '/' expr
    | expr '%' expr
    | expr '&' expr
    | expr '|' expr
    | expr '^' expr
    | "not" expr
    | expr "==" expr
    | expr "!=" expr
    | expr '<' expr
    | expr "<=" expr
    | expr '>' expr
    | expr ">=" expr
    | expr "<<" expr
    | expr ">>" expr
    | expr "and" expr
    | expr "or" expr
    | expr '?' expr ':' expr
    | "proc" '(' declargs ')' block
    | '(' expr ')'
    ;

literal: INT
       | HEX
       | BIN
       | FLOAT
       | DOUBLE
       | COMPLEX
       | STRING
       | CHAR
       ;

call: onecall
    | call '.' onecall
    ;

onecall: lvalue '(' args ')'
       ;

args:
    | expr
    | args ',' expr
    ;

if: "if" '(' expr ')' block
  | "if" '(' expr ')' block "else" block
  ;

for : "for" '(' forarg "in" foriter ')' loop
    | "for" '(' forinit ';' expr ';' forincr ')' loop
    ;

forarg: identifier
      | "var" identifier
      ;

forinit: forinitarg
       | forinit ',' forinitarg
       ;

forinitarg: assign
          | "var" identifier '=' expr
          ;

forincr: assign
       | forincr ',' assign
       ;

foriter: lvalue
       | call
       ;

loop: ';'
    | loopblock
    ;

loopblock: '{' '}'
         | '{' loopstmts '}'
         ;

loopstmts: loopstmt
         | loopstmts loopstmt
         ;

loopstmt: "break"
        | "continue"
        | loopblock
        | stmt
        ;

while: "while" '(' expr ')' loop
     | "do" loopblock "while" '(' expr ')'
     ;

switch: "switch" '(' expr ')' '{' cases '}'
      ;

cases: allcases "default" ':' stmts
     ;

allcases: "case" expr ':' casestmts
        | allcases "case" expr ':' casestmts
        ;

casestmts: casestmt
         | casestmts casestmt
         ;

casestmt: "break"
        | caseblock
        | stmt
        ;

caseblock: '{' '}'
         | '{' casestmts '}'
         ;

Name: Anonymous 2012-01-13 23:00

I would suggest reading SICP

Name: Anonymous 2012-01-13 23:02

Objectives: simple language, generics, type inference, and unambiguous grammar.
Sounds great but you're going to ruin it somehow since you're more likely than not a mental midget.

Name: Anonymous 2012-01-13 23:03

Little remarks: I've changed the addressof operator to @, and the dereference operator to $. They look more natural IMHO.

Also, I don't know how to make unambiguous prefix ++ and -- operators. =T

Name: Anonymous 2012-01-13 23:03

* little people

Name: Anonymous 2012-01-13 23:04

>>4
I've changed the addressof operator to @, and the dereference operator to $
You've already ruined it, great job.

Name: Anonymous 2012-01-13 23:06

>>2 Sir! I'm doing it, sir!
>>3 Yes I know... But at least I expect to learn something from it, and spend more time programming than posting shit.

Name: Anonymous 2012-01-13 23:09

>>4
Also, I don't know how to make unambiguous prefix ++ and -- operators.
You fix them by removing them.

Name: Anonymous 2012-01-13 23:10

>>8 It's why I commented them out. So there isn't any other way?

Name: Anonymous 2012-01-13 23:24

>>9
They should already be unambiguous. What exactly is the problem? The typical way to disambiguate the operators is by placing spaces to separate the tokens, as in i++ + + ++j. Did you make sure the lvalue wasn't being reduced to an expr before the parser receives the "++" token?

Name: Anonymous 2012-01-14 4:15

Is this some hobby project to teach yourself something?

Name: Anonymous 2012-01-14 7:01

>>4
I've changed the addressof operator to @, and the dereference operator to $. They look more natural IMHO
That's ridiculous, why change something that works, why change something everybody knows what is and does?

Name: Anonymous 2012-01-14 10:14

>>10 Yes, it is being reduced to expr. =T

>>11 A hobby, yes. But I'm taking it seriously for real usage.

>>12 I tweaked the precedence a little, so they don't behave as & and *. I'm just trying to get something like $a.$b.$b = 1 which is equivalent to *(a->b->b) = 1;

Other toughts:
I haven't decided [yet] how to put template parameters on function calls and types. Functions definitely will be first-class citizens, but I'm not sure about types...

Name: Anonymous 2012-01-14 10:51

>>13
$a.$b.$b = 1
Pig disgusting and not well known.

*(a->b->b) = 1
Beautiful and well known to anyone who is familiar with C or C++.

Name: Anonymous 2012-01-14 11:05

>>13
I haven't decided [yet] how to put template parameters on function calls and types. Functions definitely will be first-class citizens, but I'm not sure about types...
Don't make the same mistake as C and C++:
1. Types after the variable: x τ or possibly x : τ.
2. Return type after the argument list: f(x : int) -> int.
3. In a type annotation, an unbound type is a type variable: f(x : α) -> int has type ∀α.α→int.
4. Distinguish the type declaration from the function declaration (which is why you should be using a colon between a variable and its type)
All of these should compile:
f(x : α, y : β) -> int { return 1; }
f : (α, β) -> int;
f(x : α, y : β) -> int { return 1; }

f : (α, β) -> int;
f(x, y) { return 1; }

6. Make structs take type variables:
struct list(α) { car : α; cdr : maybe(list(α)) }

Name: Anonymous 2012-01-14 11:10

>>15
That's disgusting.

Name: Anonymous 2012-01-14 11:14

>>14
Not really.
Some languages (i.e. sh) use $IDENTIFIER as variable names, so I'm using a similar approach.
It's also easier to spot when reading code, and provides an uniform syntax too (instead of C ->).

Name: Anonymous 2012-01-14 11:21

>>17
You're a fucking moron.

Name: Anonymous 2012-01-14 11:36

>>15
3. In a type annotation, an unbound type is a type variable: f(x : α) -> int has type ∀α.α→int.
Terrible! So instead of showing an error if you have a typo, it will accept it as a type variable. I like the way Haskell does this (types are capitalized, type variables are lowercase) but that will probably look pretty bad in a C-like language. Maybe the other way around? f : (int, A) -> A

Name: Anonymous 2012-01-14 11:44

I am going to be a contrarian... I like the @ and $ operators, OP. You reference and dereference so often in low level code that they really should have their own dedicated operators. It is an excellent idea.

Name: Anonymous 2012-01-14 11:44

>>19
Point taken.
I was thinking the same, the forced capitalization of types would look bad in a C-like language. I haven't thought of doing the reverse, though.

Name: Anonymous 2012-01-14 11:50

>>16 Not at all.

>>15
x : τ
I was using this before, it was just dropped to support the ?: operator. Also, var declarations looked strange:

  def f(x:α, y:β) {
    var c = x + y
    d:float = distance(x, y)
  }


There's a const declaration too(def c = 4), but I don't think this is really needed, a compiler should be able to detect the lack of assignments, right?

Damn, I'll just change the var declarations to ML let.
Oh! struct list(α) { ... } looks good, thank you for the advice.

Name: Anonymous 2012-01-14 11:51

>>22
If you were to continue with name:type I would do something like:


d:float = distance(x, y)
c := x + y

Name: Anonymous 2012-01-14 11:57

>>22
I was using this before, it was just dropped to support the ?: operator.
Make if..else an expression and not a statement. I beg you.
Also, var declarations looked strange:
var x:τ = 2+2?
Also, with type inference, that's not going to be much of an annoyance.
a compiler should be able to detect the lack of assignments, right?
Right, but mutability (or immutability) annotations help a whole lot.

Name: Anonymous 2012-01-14 12:02

>>18 Thank you, pal! Nice argument.
>>19,21 Maybe adding [another] operator? Like def f(x:T?) { return x }.
>>23 Not sure but I'll think about it.

Name: Anonymous 2012-01-14 12:06

>>24 Ok. What about {let} to annotate scoped constants?
{def f(x, y) {
    let s = log(x, y)
    for (var t in range(x)) {
        ...
    }
}}

Name: Anonymous 2012-01-14 12:09

>>19,21,25
Or def f(var x : τ) {...}
Or def f(x : var τ) {...}

Name: Anonymous 2012-01-14 12:18

>24
About if..else, I don't know, since blocks don't require exprs. Maybe return 0 or define an ifblock terminating in an expr?

Name: Anonymous 2012-01-14 12:20

>>25
Maybe adding [another] operator?
That would be the ML solution, where 'a -> int is the type ∀a.a→int. Personally, I find it disgusting.
Maybe an explicit forall quantifier, or f[a](x : a) -> int, but then the function declaration syntax becomes too bloated, and separate-type-declaration-unfriendly.

>>26
def was ok. I'd say to not introduce another keyword for function, variable, constant definitions. let or def for functions and constants, var for variables is my suggestion.

Name: kodak_gallery_programmer !!kCq+A64Losi56ze 2012-01-14 12:23

I think my IQ just dropped 20 points after reading this crap.

Name: Anonymous 2012-01-14 12:24

I like scala's approach, var for variables and val for constants (values).

Name: Anonymous 2012-01-14 12:27

It only took a couple of posts for this new language to fail horribly.

Name: Anonymous 2012-01-14 12:27

>>30
No you're a mental midget as well. How does it feel?

Name: Anonymous 2012-01-14 12:29

So this is a broken Frankenstein/Haskell of some sort?

Name: Anonymous 2012-01-14 12:29

>>28
The empty block returns either the unit type (that is, ()), or the void type, since this is a C-like language.
let x = if (true) {} else {} has the same effect of let x = f(), where f returns unit/void.

Also, remember: dangling else is considered harmful.

Name: Anonymous 2012-01-14 12:29

>>33
nice dubs

Name: Anonymous 2012-01-14 12:30

>>30
Dear mr. kodak_gallery_programmer!!kCq+A64Losi56ze,

Sorry, I can't give your lost IQ back, but instead, I would advise you to not spend your time on this textboard.

Thank you for your attention,
long long int

Name: Anonymous 2012-01-14 12:30

>>34
8/10

Name: Anonymous 2012-01-14 12:32

>>37
I spend more time on comp.lang.c because my gay lover Eric Sosman hangs out there.

Name: Anonymous 2012-01-14 13:10

>>39

Uncle Eric is mentioned in the following url...

http://www.redbooks.ibm.com/abstracts/sg247162.html

Name: Anonymous 2012-01-14 13:30

Ok, I added C-like array initializers (var x : list[int] = {1,2,3}; var g : Game = {"loser", 0}) and pointer types (var y : ptr[int]) to the grammar.

But for now I'll take some time (maybe one week?) to mature ideas before writing the AST to LLVM backend.

Also guys, thanks for your time and help.

Name: Anonymous 2012-01-14 15:13

>>41
Didn't you have type inference?

What about var x = {1,2,3}?

Name: Anonymous 2012-01-14 15:35

>>42
Yes, it's just an bad example :P
Here, a parseable n-body code (translated from http://shootout.alioth.debian.org/u32/program.php?test=nbody&lang=gcc&id=1):
let PI = 3.141592653589793
let SOLAR_MASS = 4 * PI * PI
let DAYS_PER_YEAR = 365.24

def main(args : array[string]) {
    let n = parseInt(args[1])
    var system = createSystem()
   
    printf("%.9f\n", energy(system))
   
    for (var i = 0; i < n; i++) {
        advance(system, 0.01)
    }
   
    printf("%.9f\n", energy(system))
}

def createSystem() {
    var sun : Body = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, SOLAR_MASS }
    var jupiter : Body = {
         4.84143144246472090e+00,
        -1.16032004402742839e+00,
        -1.03622044471123109e-01,
         1.66007664274403694e-03 * DAYS_PER_YEAR,
         7.69901118419740425e-03 * DAYS_PER_YEAR,
        -6.90460016972063023e-05 * DAYS_PER_YEAR,
         9.54791938424326609e-04 * SOLAR_MASS
    }
    var saturn : Body = {
         8.34336671824457987e+00,
         4.12479856412430479e+00,
        -4.03523417114321381e-01,
        -2.76742510726862411e-03 * DAYS_PER_YEAR,
         4.99852801234917238e-03 * DAYS_PER_YEAR,
         2.30417297573763929e-05 * DAYS_PER_YEAR,
         2.85885980666130812e-04 * SOLAR_MASS
    }
    var uranus : Body = {
         1.28943695621391310e+01,
        -1.51111514016986312e+01,
        -2.23307578892655734e-01,
         2.96460137564761618e-03 * DAYS_PER_YEAR,
         2.37847173959480950e-03 * DAYS_PER_YEAR,
        -2.96589568540237556e-05 * DAYS_PER_YEAR,
         4.36624404335156298e-05 * SOLAR_MASS
    }
    var neptune : Body = {
         1.53796971148509165e+01,
        -2.59193146099879641e+01,
         1.79258772950371181e-01,
         2.68067772490389322e-03 * DAYS_PER_YEAR,
         1.62824170038242295e-03 * DAYS_PER_YEAR,
        -9.51592254519715870e-05 * DAYS_PER_YEAR,
         5.15138902046611451e-05 * SOLAR_MASS
    }
    var system = { sun, jupiter, saturn, uranus, neptune }
    var px = 0.0
    var py = 0.0
    var pz = 0.0
    for (var body in system) {
        px += body.vx * body.mass
        py += body.vy * body.mass
        pz += body.vz * body.mass
    }
    offsetMomentum(sun, px, py, pz)
    return system
}

struct Body {
    x  : double
    y  : double
    z  : double
    vx : double
    vy : double
    vz : double
    mass : double
}

def offsetMomentum(p, x, y, z) {
    p.vx = -x / SOLAR_MASS
    p.vy = -y / SOLAR_MASS
    p.vz = -z / SOLAR_MASS
}

def advance(system, dt) {
    for (a in system) {
        for (b in system) {
            let dx = a.x - b.x
            let dy = a.y - b.y
            let dz = a.z - b.z

            let dSquared = dx * dx + dy * dy + dz * dz
            let distance = sqrt(dSquared)
            let mag = dt / (dSquared * distance)

            a.vx -= dx * b.mass * mag
            a.vy -= dy * b.mass * mag
            a.vz -= dz * b.mass * mag

            b.vx += dx * a.mass * mag
            b.vy += dy * a.mass * mag
            b.vz += dz * a.mass * mag
        }
    }
    for (body in system) {
        body.x += dt * body.vx
        body.y += dt * body.vy
        body.z += dt * body.vz
    }
}

def energy(system) {
    var e = 0.0
    for (a in system) {
        e += 0.5 * a.mass
                 * ( a.vx * a.vx
                   + a.vy * a.vy
                   + a.vz * a.vz )
        for (b in system) {
            let dx = body.x - b.x
            let dy = body.y - b.y
            let dz = body.z - b.z
            let distance = sqrt(dx*dx + dy*dy + dz*dz)
            e -= (a.mass * b.mass) / distance
        }
    }
    return e
}

Name: Anonymous 2012-01-14 15:40

>>43 Some remarks:

I miss sexprs here T-T:
        e += 0.5 * a.mass
                 * ( a.vx * a.vx
                   + a.vy * a.vy
                   + a.vz * a.vz )


C programmers will ask for multiple variable declarations, if they have the same type. I thought something like this.
struct Body {
    x, y, z, vx, vy, vz, mass : double
}

Name: Anonymous 2012-01-14 16:05

Does "proc" work like this?
def outer() {
     return proc (x) {
          return x*2
     }
}
outer()(10)

Name: Anonymous 2012-01-14 16:17

>>43
Not enough π decimals! 3.1415926535897932384626433

It looks good, and now I see why * isn't the dereference operator, you can drop the semicolons and make a\n*b mean a*b.

Name: long long 2012-01-14 17:04

>>45
Yes, but I was thinking about currying:
def mul(x) {
    return proc (y) { return x*y }
}
def main() {
    printf("%d\n", mul(2)(4))
}

8
But I didn't think about name binding yet.

>>46 :P
Also, I was seriously thinking in overloading the . operator to derefence pointers when accessing members, and turning $ to:
lvalue: '$' identifier
       | '$' '(' lvalue ')'

and these expressions would be equivalent:
$a*a
a.b.ca->b->c
$(a.b.c)*(a->b->c)

The verbose alternative can show what names are pointers in expressions like $a.b.$c.d, but I don't think this is a really great advantage, because if someone changes a member to a pointer, then we need to update all the code accessing it.

Name: Anonymous 2012-01-14 22:32

2012
not using off-side rule

Name: Anonymous 2012-01-14 22:51

>>48
If you're talking about indentation-based statement grouping, it has some implications that aren't good, at least for language tools.
Since often there isn't enough visual clue to distinguish different amount or types of whitespaces, I don't mind to ignore them entirely on the lexer.

Name: Anonymous 2012-01-14 23:04

>>48
FIOC is shit

Name: long long 2012-01-14 23:41

Another valid program, mandelbrot, gave [or reassured] me some ideas:
* C-compatible ABI (a must)
* importing C headers direcly (it would be good)
* implicit conversion between pointer types / void pointer?
* cpp-like preprocessor, only for #pragmas?
* optional non-qualified imported identifiers if there aren't conflicts?
* OS/arch dependent modules, like the std.sse below?
* modules could specify proper compilation flags, like
        std.sse specifying -mfpmath=sse -msse
        openmp specifying -openmp
        gl specifying -lgl
     which could also ease library dependency chains.

import openmp
import std.sse as sse
import posix
import stdlib

//
// Translated from http://shootout.alioth.debian.org/u32/program.php?test=mandelbrot&lang=gcc&id=4
//

let zero : sse.v2df = { 0.0, 0.0 }
let four : sse.v2df = { 4.0, 4.0 }

var bytes_per_row : int
var inverse_w : double
var inverse_h : double
var N : int

var Crvs : ptr[sse.v2df]
var bitmap : ptr[byte]

def main(args : array[string]) {
    N = atoi(args[1])
   
    bytes_per_row = (N + 7) >> 3

    inverse_w = 2.0 / (bytes_per_row << 3)
    inverse_h = 2.0 / N
   
    if (posix_memalign(@Crvs, sizeof(sse.v2df), sizeof(sse.v2df) * N / 2)) {
        return EXIT_FAILURE
    }

    #omp parallel for
    for (var i = 0; i < N; i += 2) {
        var Crv : sse.v2df = { (i+1.0)*inverse_w-1.5, (i)*inverse_w-1.5 }
        Crvs[i >> 1] = Crv
    }

    bitmap = calloc(bytes_per_row, N)
    if (bitmap == NULL) {
        return EXIT_FAILURE
    }

    #omp parallel for schedule(static,1)
    for (var i = 0; i < N; i++) {
        calc_row(i)
    }

    printf("P4\n%d %d\n", N, N)
    fwrite(bitmap, bytes_per_row, N, stdout)

    free(bitmap)
    free(Crvs)
    return EXIT_SUCCESS
}

def calc_row(y) {
    let row_bitmap = bitmap + (bytes_per_row * y)
    let Civ_init : sse.v2df = { y*inverse_h-1.0, y*inverse_h-1.0 }

    for (var x = 0; x < N; x += 2)
    {
        var Crv = Crvs[x >> 1]
        var Civ = Civ_init
        var Zrv = zero
        var Ziv = zero
        var Trv = zero
        var Tiv = zero
        var i = 50
        var two_pixels : int
        var is_still_bounded : sse.v2df

        do {
            Ziv = (Zrv*Ziv) + (Zrv*Ziv) + Civ
            Zrv = Trv - Tiv + Crv
            Trv = Zrv * Zrv
            Tiv = Ziv * Ziv

            is_still_bounded = sse.cmplepd(Trv + Tiv, four)

            two_pixels = sse.movmskpd(is_still_bounded)
           
            i--
        } while (i > 0 and two_pixels)

        two_pixels <<= 6

        let b : byte = two_pixels >> (x & 7)
        row_bitmap[x >> 3] |= b
    }
}

Name: Anonymous 2012-01-15 7:31

>>47
How about just '$' lvalue? Also, I think $a.b.$c.d is better.

>>51
* implicit conversion between pointer types / void pointer?
With parametric polymorphism, you can just return a polymorphic pointer:
malloc : (int) -> ptr[α]
The type α can be inferred from context and use.
Now your code is type-safe, congratulations.
* cpp-like preprocessor, only for #pragmas?
Pragma comments like Haskell.

Name: Anonymous 2012-01-15 8:49

>>51
This is a fucking nightmare, you're butchering this more and more, so every object file has to carry what it should be linked with? How else is the linker supposed to know what link with when you decide to merge all the object files into a shared object or something of that sort?

Name: Anonymous 2012-01-15 11:26

>>52
You can write a function and pass pointers or references to it:
def getm(obj) { return obj.m }
var s = {1,2,3}
getm(s)  // getm(s :     array[int] ) → int
getm(@s) // getm(s : ptr[array[int]]) → int


>>51
I was thinking in compiling to some sort of intermediate representation [just one step back from the llvm-as], that could be portably executed in a VM [for easy distribution], and also natively compiled [for -march=native -mtune=native speed].
This representation also will help distributing libraries with generic functions/structs, whose types will be inferred at compile time, generating instances. Just include a simple “make” in the compiler: you can pass source and output directories, and the source tree is recursively searched for source files, which will be compiled if its or any of its imports timestamp [recursively and cached] are newer than the matching object file in the output directory. Then we can remember the template occurrences with same type parameters in the source tree and compile each just once.

I did this for my C++ projects, 200 lines of python [except the template caching part] and it runs very nice, I can even parallelize all sources until all memory is consumed by the compiler.

$ cd ~/foo
$ make
./make.py -ssrc -obuild -j3 gcc debug
compiling src/a.cc     to build/gcc-debug/a.o
compiling src/b.cc     to build/gcc-debug/b.o
compiling src/bar/b.cc to build/gcc-debug/bar_b.o
(waiting sources compilation)
linking build/*.o      to build/gcc-debug/foo.exe


Without breaking a sweat. Compiler flags [for platform dependent CFLAGS/LDFLAGS] are put in a separate make.ini file, under different sections ([default] [win32] [linux64]).

Name: long long 2012-01-15 11:42

>>53 Sorry for mistyping, the half bottom of >>54 is for you.

Name: Anonymous 2012-01-15 16:14

>>55
What you posted has nothing to do with the issue in >>53 but okay.

Name: Anonymous 2012-01-15 16:24

>>56
Oh I see.
Maybe with some quirky #pragmas?

// module gl
#cflags.linux -lGL
#cflags.win32 -lopengl32

def glRotatef(a, x, y, z) {
·
·
·

Name: Anonymous 2012-01-15 17:17

>>57
Seems like a bad idea.

Name: OP 2012-01-26 3:49

>>59
Using for a week now, I think I'll drop the C curly braces, and switch to Algol's keyword .. end blocks. Thoughts?

Name: Anonymous 2012-01-26 4:04

>>59

whatever you'd like. Some people say end block are more readable, and other people find curlys to have a more definite structure, both for their eyes and for their text editors.

Name: Anonymous 2012-01-26 4:26

>>60
I don't know... I think that curlies could be used for something more useful, like another data structure literal (hashes?).

--
Updates:
Maybe type initializers and conversions looks better as “function calls”:
var car = Vehicle(1, 2, "Mazda")
let x = byte(car.speed & 0b11110000)


Also, I don't know if it's better to use C++'s vtables or Clay's variant types. I designed something around the second, but there's some flaws here and there yet...

Name: Anonymous 2012-01-26 6:54

>>59
Go with forced indentation, chicks dig it.

Name: Anonymous 2012-01-26 20:22

oh god, another sepples. kill it before it reproduces.

Name: Anonymous 2012-01-26 20:37

>>63
You now know how Israeli snipers feel when they see a Palestinian.

Name: Anonymous 2012-01-26 20:40

>>66
nice dubs bro

Name: Anonymous 2012-01-26 20:41

>>65
thanks

Name: Anonymous 2012-01-26 20:43

For every natural number greater than or equal to 2 there exists at least one base in which the number constitutes ``dubs''.

Name: Anonymous 2012-02-03 11:42

What's up?

How about this?

var n:int
scanf("%d", @n)
puts("[output]")
if n
is 0,1: puts("")
is 2: printf("a")
      continue
is 3: puts("b")
else: puts("c")
end


giving the result below?

$ cat | ./a.out
0
1
2
3
4^D
[output]


ab
b
c

Name: Anonymous 2012-02-04 1:50

ponup

Name: Anonymous 2012-02-04 4:12

>>67
nice base 66 dubs

Name: Anonymous 2012-02-04 4:29

>>70
I just realized... all numbers are [dubs-base0,...,-dubs-basen] dubs for some n.

Name: Anonymous 2012-02-04 15:24

>>71

except for 1, silly billy.

Name: Anonymous 2012-02-04 20:40

>>72
Or 2.

Don't change these.
Name: Email:
Entire Thread Thread List