inca: a hacked-up apl in c based on the J incunabulum


L

luser- -droog

compiles without warnings (if you don't ask for warnings) with gcc. currently 313 terse lines.

https://github.com/luser-dr00g/inca

Questions? Improvements? Style-bashing?

inca
====

based on the J-incunabulum,
http://www.jsoftware.com/jwiki/Essays/Incunabulum
lightly extended to allow propagating specifications "a+2+a=3",
new functions minus,times,unbox. multi-digit integers.
identity element for monadic use of minus,times,cat.

Implements monadic functions

+ identity
{ size
~ iota
< box
# shape
| absolute
! not
' transpose
@ reverse

dyadic functions

+ plus
{ from
~ find
< assign (not really a function, but an interpreter action)
# reshape
, cat
- minus
. times
* power
% divide
| modulus
& and
^ or
= equals?

monadic operator

/ reduce f/X => x0 f (x1 f (x2 f ( ... xn-2 f xn-1)))

dyadic operator

. matrix product Af.gW => f/Ag'W

over multidigit numbers and variables
'_'(underscore), '`'(backtick), and a-z
`'_'`(underscore) is set to the result of the previous line.

The interpreter also implements a non-greedy "cat" for
number vectors separated by spaces. Hence `1 2 3+~3` => `1 3 5`
where `~` is the zero-based iota.

If the length of the command string exceeds 98 characters,
the behavior is undefined.

If array operands have incompatible sizes, the behavior
is undefined.
 
Ad

Advertisements

J

jacob navia

gcc -g miniapl.c
[ many warnings ellided ]
gdb ./a.out
warning: this program uses gets(), which is unsafe.
1 + 1

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00000005
0x00003524 in cat (a=0x17ff10, w=0x1) at miniapl.c:107
107 V2(cat){I an=tr(a->r,a->d),wn=tr(w->r,w->d),n=an+wn;
(gdb) print *a
$1 = {
t = 0,
r = 0,
d = {0, 0, 0},
p = {1, 0}
}
Current language: auto; currently minimal
(gdb) quit
The program is running. Exit anyway? (y or n) y

Obviously I am too stupid to understand

V2(cat){I an=tr(a->r,a->d),wn=tr(w->r,w->d),n=an+wn;

1) You use "P" for printf
2) You use "R" instead of return
3) C for "char"
4) "I" for int
5) No identifier name is longer than two letters
6) The result of a function is never declared. Implicit int for all
functions
7) The type of variables is never declared. Implicit int for all variables.

So, you publish code that only you can read. GREAT!
 
L

luser- -droog

So, you publish code that only you can read. GREAT!

Perhaps a select few others across this wide globe.

It's definitely a hornet's nest of a pile of code droppings.
But it kinda all works, if you type the syntax right.

In your attempt, the spacing was off.

1+1
should work. A space following a number must be
followed by another number, and it concatenates
the two into a list terminated by the first
operator/function.

1 1 1+3 => 4 4 4

It took me weeks poring over that original J
incunabulum. Then learning more apl for context,
then going back to the incunabulum.

The "byte"-code (actually, integer-code) format
distinguishes between types by ranges.
x < 16ish : it's a function or operator
x >= '_' && x <= 'z' : it's a variable
x > 'z' : it's a pointer

This makes the assumption that pointer values
in the ascii range are never returned by malloc.
 
B

BartC

luser- -droog said:
compiles without warnings (if you don't ask for warnings) with gcc.
currently 313 terse lines.
https://github.com/luser-dr00g/inca

Questions? Improvements? Style-bashing?

The C code very cleverly resembles APL too.
If the length of the command string exceeds 98 characters,
the behavior is undefined.

Can't you just increase the s[99] in main() to something less likely to be
exceeded? Such as s[999]. It will still be 313 lines (or 314 as it appears
to be now).
 
L

luser- -droog

The C code very cleverly resembles APL too.

That part comes from the original source,
but I've tried to stay true to the original style.
But there are numerous //commented printfs where
I've needed to probe what it was doing.
If the length of the command string exceeds 98 characters,
the behavior is undefined.


Can't you just increase the s[99] in main() to something less likely to be
exceeded? Such as s[999]. It will still be 313 lines (or 314 as it appears
to be now).

Certainly that can be done, but it still needs the scary
warning, I think.
 
Ad

Advertisements

L

luser- -droog

The part I'm really proud of is getting it to do a
matrix product:
86400 3600 60 1+..0 2 1 18
=> 7278 .

The first dot is "dot-product", the second dot is "product".

I thought about making "power" an operator instead of a function, but it got too weird to think about.

or never got weird enough, maybe.


In order to do "base" and "encode" like the APL book describes, I'll need to generate a triangular matrix. And probably a whole prototype matrix family.

So I'm thinking that'll be a dyadic operator, similar to the circle functions, and maybe I can do rotation/transposition the same way.

And at some point, I'll want to extend it to handle floating-point numbers and character strings.

With strings, it can invoke execute as a function, and then variables can hold code.

Unfortunately, I can't use "dot" as a floating-point notation if it's overloaded already as a function and an operator. :(
 
D

David Brown

gcc -g miniapl.c
[ many warnings ellided ]
gdb ./a.out
warning: this program uses gets(), which is unsafe.
1 + 1

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00000005
0x00003524 in cat (a=0x17ff10, w=0x1) at miniapl.c:107
107 V2(cat){I an=tr(a->r,a->d),wn=tr(w->r,w->d),n=an+wn;
(gdb) print *a
$1 = {
t = 0,
r = 0,
d = {0, 0, 0},
p = {1, 0}
}
Current language: auto; currently minimal
(gdb) quit
The program is running. Exit anyway? (y or n) y

Obviously I am too stupid to understand

V2(cat){I an=tr(a->r,a->d),wn=tr(w->r,w->d),n=an+wn;

1) You use "P" for printf
2) You use "R" instead of return
3) C for "char"
4) "I" for int
5) No identifier name is longer than two letters
6) The result of a function is never declared. Implicit int for all
functions
7) The type of variables is never declared. Implicit int for all variables.

So, you publish code that only you can read. GREAT!

I guess the original author wanted to write something akin to APL, but
which could be accepted by a C compiler.
 
D

David Brown

The C code very cleverly resembles APL too.

That part comes from the original source,
but I've tried to stay true to the original style.
But there are numerous //commented printfs where
I've needed to probe what it was doing.
If the length of the command string exceeds 98 characters,
the behavior is undefined.


Can't you just increase the s[99] in main() to something less likely to be
exceeded? Such as s[999]. It will still be 313 lines (or 314 as it appears
to be now).

Certainly that can be done, but it still needs the scary
warning, I think.

An APL program that exceeds 98 characters is scary - one that exceeds
998 characters would be terrifying. I don't think a warning is needed!
 
J

jacob navia

Le 27/03/2014 12:23, David Brown a écrit :
I guess the original author wanted to write something akin to APL, but
which could be accepted by a C compiler.
I have programmed in APL for years. I worked in STSC, the main APL
provider in the 80s, and always my variable names were clear mnemonic
names. APL is succint, yes, but if you use it correctly you can write
quite readable software.

Besides, there is no point in using gets() for a fixed length line.
lcc-win provides "getline()" and many other compilrs do that too.
 
D

David Brown

Le 27/03/2014 12:23, David Brown a écrit :
I have programmed in APL for years. I worked in STSC, the main APL
provider in the 80s, and always my variable names were clear mnemonic
names. APL is succint, yes, but if you use it correctly you can write
quite readable software.

APL is only readable if you have learned to understand the symbols, and
if you have learned to understand the way of thinking (right-to-left
parsing without operator precedence, so that 4 * 2 + 3 is 20 in APL).
So you need to reach a higher level of understanding in APL than many
other languages before anything is comprehensible. Personally, I never
got anywhere near that stage when I played a little with APL some 25
years ago.

But of course you can write more or less readable code in APL, just as
you can in C and any other language. It is just that with APL, you can
take compact and virtually incomprehensible code to new heights that
would make any IOCC winner cry. You can also write code that /looks/
like it is a compact and incomprehensible collection of symbols, while
it is actually perfectly readable to APL experts - you can't do that with C.
 
Ad

Advertisements

K

Keith Thompson

luser- -droog said:
compiles without warnings (if you don't ask for warnings) with
gcc. currently 313 terse lines.

https://github.com/luser-dr00g/inca

Questions? Improvements? Style-bashing?
[...]

typedef char C;
typedef intptr_t I;
typedef struct a{I t,r,d[3],p[2];} *A;
[...]

#define P printf
#define R return

And that's where I stopped reading.

I'm curious, though. Why would you write code like that? Is it
deliberately obfuscated?

Oh, and inca.c will not compile, since the name intptr_t is not visible.
(This isn't just an error in the current versions; all 27 versions in
your repository have the same problem.) If it compiles without error
for you, there may be something wrong with your C implementation.

Once you fix that, try compiling on a 64-bit system.
 
K

Keith Thompson

Javier Lopez said:
El 27/03/2014 8:53, luser- -droog escribió:
Good for IOCCC ;)
http://www.ioccc.org/

Not really. IOCCC requires more creative obfuscation than hacks like
"#define R return" that can be resolved just by running the code through
the preprocessor (which the judges will do).
 
L

luser- -droog

luser- -droog said:
compiles without warnings (if you don't ask for warnings) with
gcc. currently 313 terse lines.

https://github.com/luser-dr00g/inca

Questions? Improvements? Style-bashing?

[...]

typedef char C;
typedef intptr_t I;
typedef struct a{I t,r,d[3],p[2];} *A;
[...]

#define P printf
#define R return

And that's where I stopped reading.

I'm curious, though. Why would you write code like that? Is it
deliberately obfuscated?

As you've commented elsewhere in this thread, it is
/obscure/ but not very /obfuscated/, per se.

The goal I think, is compactness. I've lost some
of that while adding extensions, but I'm still trying
to keep it "tight", while removing limitations and
errant behavior.
Oh, and inca.c will not compile, since the name intptr_t is not visible.
(This isn't just an error in the current versions; all 27 versions in
your repository have the same problem.) If it compiles without error
for you, there may be something wrong with your C implementation.

Cygwin gcc (GCC) 4.5.3 let me get away with it.
But I've added said:
Once you fix that, try compiling on a 64-bit system.

{shudder}. Touché.
 
B

BartC

luser- -droog said:
As you've commented elsewhere in this thread, it is
/obscure/ but not very /obfuscated/, per se.

The goal I think, is compactness. I've lost some
of that while adding extensions, but I'm still trying
to keep it "tight", while removing limitations and
errant behavior.

Why is it necessary to keep it tight?

(I had a look earlier with a view to expanding it to 'normal' C. But after
about thirty seconds I gave up! It would be easier to rewrite from scratch.)
 
Ad

Advertisements

J

Javier Lopez

El 27/03/2014 19:04, Keith Thompson escribió:
Not really. IOCCC requires more creative obfuscation than hacks like
"#define R return" that can be resolved just by running the code through
the preprocessor (which the judges will do).
If this wasn't intented for a obfuscation contest, then it is
deliberately obfuscated and I don't understand the point.
 
J

James Kuyper

typedef char C;
typedef intptr_t I;
typedef struct a{I t,r,d[3],p[2];} *A;
[...]

#define P printf
#define R return

And that's where I stopped reading.

I'm curious, though. Why would you write code like that? Is it
deliberately obfuscated?

As you've commented elsewhere in this thread, it is
/obscure/ but not very /obfuscated/, per se.

The goal I think, is compactness.

That's a pretty nearly worthless goal to be pursuing, and you're
pursuing at great expense to readability, a far more important goal.
 
K

Keith Thompson

luser- -droog said:
luser- -droog said:
compiles without warnings (if you don't ask for warnings) with
gcc. currently 313 terse lines.

https://github.com/luser-dr00g/inca

Questions? Improvements? Style-bashing?

[...]

typedef char C;
typedef intptr_t I;
typedef struct a{I t,r,d[3],p[2];} *A;
[...]

#define P printf
#define R return

And that's where I stopped reading.

I'm curious, though. Why would you write code like that? Is it
deliberately obfuscated?

As you've commented elsewhere in this thread, it is
/obscure/ but not very /obfuscated/, per se.

The goal I think, is compactness. I've lost some
of that while adding extensions, but I'm still trying
to keep it "tight", while removing limitations and
errant behavior.

My comment was that its obfuscation would not be suitable for the IOCCC
(http://www.ioccc.org/).

That kind of compactness is not a virtue. Abbreviating "return" and
"printf" (which all C programmers understand) as "R" and "P" serves no
useful purpose that I can think of. I for one will not waste my time
trying to read code written in that horrid style.

(Apparently there are other problems as well, such as depending on
implicit int and assuming that int and pointers are the same size.)

If you find it fun to write such code for yourself, you are of course
free to do so. If you want anyone else to read it, as implied by
posting it here, going out of your way to make it more difficult
to read is counterproductive.
 
Ad

Advertisements

G

glen herrmannsfeldt

(snip, someone wrote)
That's a pretty nearly worthless goal to be pursuing, and you're
pursuing at great expense to readability, a far more important goal.

There are still a few cases left where compact is fast, and fast
is important. For real-time systems, it is either fast enough or
doesn't work at all.

The inner loop of an interpreter should also be fast, sometimes
at the expense of readability. (Though there is no excuse
for not having enough comments to explain the unreadable part.)

-- glen
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top