Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

IVY: a new language

24 views
Skip to first unread message

Joseph H Allen

unread,
Oct 31, 2005, 9:22:32 PM10/31/05
to

What is it?

Ivy 2005 is the latest version of the scripting language I wrote originally
in 1993. This version adds an extensible syntax and is designed to be
embedded in my test editor JOE. It is just starting to work, so I've
uploaded it to sourceforge.

Where to get it?

CVS checkout from http://sourceforge.net/projects/ivy-lang

Extensible syntax

By "extensible syntax" I mean that you can define new statements in the
language just by declaring new functions. The trick then is to make
functions powerful enough to do the same things that statements can do:
delayed evaluation and messing around with scope.

For example, here is a function for a text editor which allows the body code
to move the cursor. When the code is complete, the cursor is automatically
restored (akin to unwind-protect in LISP):

fn excursion(&body)
var save = cursor
var rtn = *body
cursor = save
(rtn)

The '&' prefixing the formal argument indicates that the code for that
argument should not be evaluated immediately (as would normally be done in
this pass-by-value language), but to instead delay its evaluation (the
argument is packaged up as a function in its closure). The '*' causes the
function to be called (evaluated). In LISP, this would all be done with
quoting or macros.

Other features

Ivy's interpreter and parser are both event driven. For example, when an
Ivy program calls a C-language function, it returns from the interpreter
and return a pointer to the C-language function to the caller. When the
C-function is done, the interpreter should be called again.

This means Ivy can be used in a co-operative multi-threaded environment:
think of a command interpreter for a MUD.

In Ivy everything is a function, but to make statements look "normal" (and
to separate statments out from the parser as in LISP), there is a "command"
format for function calls. Basically, these are the same:

func(x,y,z)
func x y z

Block structuring can be indicated by square brackets or indentation:

# Indented blocks of commands
foreach a {1 2 3}
if a==2
print "There's a 2"
print "Hello"

# square bracket blocks of commands
[foreach a {1 2 3} [if a==2 [print "There's a 2"; print "Hello"]]]

# Expressions
foreach(a,{1 2 3},if(a==2,print("There's a 2")\print("Hello")))

Indentation is preferred for blocks, but square brackets are convenient for
when Ivy is used interactively. A generic method of passing multiple
indented blocks to a function is provided. This:

if a==1
print "It's a 1"
next a==2
print "It's a 2"
last
print "It's something else"

Is the same as this:

if(a==1,print("It's a 1"),a==2,print("It's a 2"),print("It's something else"))

And can be used for your own functions:

fred a==1
print "It's a 1"
next a==2
print "It's a 2"
last
print "It's something else"

'fred' gets passed 5 arguments.

Ivy is compiled to byte-code, which is then interpreted. Type checking is
done at run time. It is a late binding language, meaning that variable name
to value bindings happen late (basically there's a hash table lookup
whenever a variable is accessed). To help make this a little faster, all
names are converted to "atoms", which are unique strings which exist at only
one address. The string's address is all that needs to be compared during
the hash table lookup. The address is used as the hash value itself: so
most variable lookups reduce to a single array access followed by a single
word compare.

Ivy has closures: you can define functions inside others, and then return
them. The returned function still have access to the creating function's
scope at the time of creation.

Ivy has lambda (nameless) functions.

print fn(x,x*x)(7) # Prints 49

Ivy has named argument passing and default argument values:

fn square(a=10,b=10) a*b

print square(`a=3)
print square(`b=4)
print square(3,5)

Ivy has command history and on-line help.

Ivy has garbage collection.

Ivy has "objects" which are a catch-all for array, structures, hashes and
tuples:

a = {1 2 3} # An array
print a(1)

a = {`a="hi" `b="there" } # A structure
print a.b

a("first") = 1 # A hash table
a("second") = 2
print a("first")

{x y z} = {1 2 3} # A tuple: assign three variables at
# once

c = {`next=(), `value=0} # A linked list
b = {`next=c, `value=1}
a = {`next=b, `value=2}

These objects are also used for closures. They are the primary data
structure of the language. When objects are used as closured, several
special members get defined:

this # The closure itself
mom # The next outer lexical scope
dynamic # The next outer dynamic scope

Ivy has a few other basic types:
"hi" # String
123 # Integer
12.3 # Double precision floating point
fn((x),x*x) # Function

Ivy has C-like operators. It also has post-assignment operators, a
generalization of C post-increment.

a=b=3 # 3 written to b, result (3) written to a
a=b:3 # 3 written to b, previous value of b written to a

a+=3 # pre-add a (returns a+3)
a+:3 # post-add a (returns old value of a)

a:b:a # swap a and b

It has an assignment form of the '.' (member selection operator). This is
convenient for traversing linked lists:

c={`next=0, `value=3}
b={`next=c, `value=2}
a={`next=b, `value=1}

for x=a, x, x.=next
print x.value

Ivy has string-slicing built-in:

a="Hello"
print a(2,5) # Prints "llo"
print a(0) # Prints "H"

Ivy has labeled break and continue:

outer: for a=0, a!=10, ++a
for b=0, b!=10, ++b
if a+b==15
break outer

Other planned features:

Exceptions.

Continuations or co-routines (haven't decided yet: leaning towards
co-routines, but designing for continuations).

First-class regular expressions, as in perl.

All UNIX system calls and library functions, as in perl.

Object oriented Ivy (you can do it now with closures, but there
is no inheritance, protection or module system).

Widget library and X interface. I'd like to use Ivy as a
replacement for "gnu-plot" (and when built into JOE, as a free
version of "mathcad").
--
/* jha...@world.std.com (192.74.137.5) */ /* Joseph H. Allen */
int a[1817];main(z,p,q,r){for(p=80;q+p-80;p-=2*a[p])for(z=9;z--;)q=3&(r=time(0)
+r*57)/7,q=q?q-1?q-2?1-p%79?-1:0:p%79-77?1:0:p<1659?79:0:p>158?-79:0,q?!a[p+q*2
]?a[p+=a[p+=q]=q]=q:0:0;for(;q++-1817;)printf(q%79?"%c":"%c\n"," #"[!a[q-1]]);}

Message has been deleted
Message has been deleted

cr88192

unread,
Oct 31, 2005, 9:54:00 PM10/31/05
to

"Joseph H Allen" <jha...@TheWorld.com> wrote in message
news:dk6jh8$oum$1...@pcls4.std.com...

>
>
> What is it?
>
> Ivy 2005 is the latest version of the scripting language I wrote
> originally
> in 1993. This version adds an extensible syntax and is designed to be
> embedded in my test editor JOE. It is just starting to work, so I've
> uploaded it to sourceforge.
>
<snip rest>

is this the same text editor as 'jmacs' (typically a symlink to 'joe'),
which came with many linux distros.

if so, that is cool. I had used that editor a lot until eventually using x11
primarily (then, switching over to gedit).

ok, eventually, I migrated back over to windows, whereby I am using
notepad...

ok, vaguely interesting.

likely the usual rules for most scripting languages apply, eg, getting
anyone to care being likely a major challenge.

now, I am off in physics-engine land, seeing if anyone will care there.
hell, at least I have less competition, but ode is pretty well seated. what
of my scripting lang (currently a language somewhere between scheme,
javascript, and self)? I don't know, probably I will continue to use that
for my stuff whenever I need a scripting language.

unsurprisingly, I doubt anyone will care much about anything I do...

(and I watch as the number of posts to this group gradually diminishes
afaict...).


Joseph H Allen

unread,
Nov 1, 2005, 1:12:01 PM11/1/05
to
In article <IVY-20051...@ram.dialup.fu-berlin.de>,
Stefan Ram <r...@zedat.fu-berlin.de> wrote:

> Mathematically, a tuple, say a 2-tuple, is defined by
> requiring that:

>(a,b)=(c,d) <==> a=c ^ b=d,

> where "^" is the logical "and".

> So IVY has tuples if after the above assignment,

>if {x y z} == {1 2 3}
> print "a"

> will print "a".

True, two tuples are the same if their components have the same value and
are in the same order... but mathematics does not require that the symbol
'==' should have this particular meaning of 'the same'. Perhaps the symbol
'===' has it (LISP has three eq's).

Joseph H Allen

unread,
Nov 1, 2005, 1:20:07 PM11/1/05
to
In article <21ec4$4366d8da$ca83a7e9$44...@saipan.com>,
cr88192 <cr8...@NOSPAM.hotmail.com> wrote:

>is this the same text editor as 'jmacs' (typically a symlink to 'joe'),
>which came with many linux distros.

Yes.

>likely the usual rules for most scripting languages apply, eg, getting
>anyone to care being likely a major challenge.

Of course: but people did switch to Python when Perl was perfectly adequate.

>(and I watch as the number of posts to this group gradually diminishes
>afaict...).

It's all been done before in LISP, so why bother :-)

Actually, USENET itself seems to be in decline. It's sad.

Message has been deleted

cr88192

unread,
Nov 2, 2005, 5:02:07 PM11/2/05
to

"Joseph H Allen" <jha...@TheWorld.com> wrote in message
news:dk8bkn$gss$1...@pcls4.std.com...

> In article <21ec4$4366d8da$ca83a7e9$44...@saipan.com>,
> cr88192 <cr8...@NOSPAM.hotmail.com> wrote:
>
>>is this the same text editor as 'jmacs' (typically a symlink to 'joe'),
>>which came with many linux distros.
>
> Yes.
>
cool.

>>likely the usual rules for most scripting languages apply, eg, getting
>>anyone to care being likely a major challenge.
>
> Of course: but people did switch to Python when Perl was perfectly
> adequate.
>

well, this one can be understood (sort of, though I am not so fond of python
either...).

>>(and I watch as the number of posts to this group gradually diminishes
>>afaict...).
>
> It's all been done before in LISP, so why bother :-)
>

yes.

mine have typically been little 'new' per se. my newest one can say
primarily "resembles javascript" but it is not javascript (some things are
different, and I couldn't make crap for sense out of the spec...).
as typically, I wrote a compiler for it as well (spews out c), but I can see
how much I use this (with a sucky/incomplete ffi, and still unimpressive
generated code, there is not that much reason to use it for much...).
I am probably the only one who uses it, but this is no big deal.

then I tried ripping off ideas from java (making a mostly statically typed
language, and a vm resembling the jvm). gave up as it was proving tedious (a
static typesystem complicates things a whole lot) and I couldn't see 'that'
much reason to continue implementing it.

actually, it would have been more of a hybrid, allowing mixing a few
different things (static and dynamic types, classes and delegation, ...). it
changed a few things vs java:
modular, instead of one class per file;
limited-scope toplevels, vs no toplevels;
plain functions as well, ...

in the simple case, the code would likely look very similar to java.
I also considered the possibility of using java itself, but noted that it
had little hope of effectively managing dynamic typing, and a few other
things I didn't really like (I also wanted operator overloading, for
example).

java also didn't have the idea of stack-allocated/in-place arrays or
structures, which was a detractor.
my design included 'structs', where structs differed primarily from classes
in that:
they were allocated in place;
they were passed by value;
(considered) disallowing extending and methods.

if extending were allowed, it would be limited, eg, in that a derived struct
couln't generally be passed to something expecting the parent type due to
size issues. methods would be limited, if present at all (no non-static
methods, unless explicitly part of the struct body).

arrays were similar:
int foo[3]; //creates an in-place array;
int foo[]=new int[3]; //creates a dynamic array

...


reasons for it:
likely more efficient with memory;
possibly faster interpreter;
less ffi work needed (typesystem would be much closer to c);
possibly worthwhile generated c code, and the ability to call directly
to/from the language (my other langs have typically required 'stubs' to
convert arg/return types back and forth and do the calls);
...

against:
I allready have a working interpreter for my other lang;
the effort required for implementing it;
...

dunno, I could continue if I saw a reason.

> Actually, USENET itself seems to be in decline. It's sad.
>

yes, it used to be that I could actually watch stuff being talked about on
all the groups. over time, everywhere gets more and more empty...

Joseph H Allen

unread,
Nov 3, 2005, 9:37:53 AM11/3/05
to
In article <bad88$4369376a$ca83a7e9$27...@saipan.com>,
cr88192 <cr8...@NOSPAM.hotmail.com> wrote:

>...static typing is tedious...

It's so limiting.. but it's fast.

I was looking into macros for Ivy at point and came across in interesting
paper. Some scheme programmer came up with the idea of first class macros
in a statically typed language (so you can return a macro and call it).
What he realized was that this would be possible if macros had types. Think
about a macro which declares a variable and you'll see the need for this.

>java also didn't have the idea of stack-allocated/in-place arrays or
>structures, which was a detractor.

(as much as it pains me to say this) You should take a look at C#. Like
Java, most things are handled by reference. But it distinguishes between
stack and heap values, especially for primitive types. When a primitive
type needs to on the heap, it gets boxed up in a class, like java. Anyway,
I think it might have stack allocated arrays, or at least stack allocated
tuples.

The stack allocation is interesting for classes. It would be nice if stack
allocated classes had their destructors called when they go out of scope, as
in C++. A version with reference counting instead of garbage collection
would also be interesting. I've seen Java programmers jump through hoops
trying to manage external resources like file-descriptors, with only
GC finalizers.

Someone needs to add templates to Java or C#: that you have to use
downcasting to make generic containers is dangerous.

cr88192

unread,
Nov 3, 2005, 7:59:12 PM11/3/05
to

"Joseph H Allen" <jha...@TheWorld.com> wrote in message
news:dkd7c1$skr$1...@pcls4.std.com...

> In article <bad88$4369376a$ca83a7e9$27...@saipan.com>,
> cr88192 <cr8...@NOSPAM.hotmail.com> wrote:
>
>>...static typing is tedious...
>
> It's so limiting.. but it's fast.
>

my idea was actually more for a hybrid, eg, statically typed core with
dynamic types as well. they would be called 'variant', and would be
processed at run-time whenever they pop up.

the compiler logic for static typing is a horrible pita though.

no longer can one, say, reduce the left and right-hand expressions (as a
simple process involving eliminating constants), then just spit out an
opcode for 'add' and be done with it.

instead, it is necessary to check the types, and generate the correct
bytecode for those types. many things can get weird as well, and one has to
worry about a lot more possible occurances during compilation.

also, one can't just insert some opcode like 'ok, go fetch this variable',
instead, one needs to locate the var exactly, and generate bytecode for
fetching it from the object or its respective place on the stack.

...

> I was looking into macros for Ivy at point and came across in interesting
> paper. Some scheme programmer came up with the idea of first class macros
> in a statically typed language (so you can return a macro and call it).
> What he realized was that this would be possible if macros had types.
> Think
> about a macro which declares a variable and you'll see the need for this.
>

ok, cool.

hmm, lispy macros in a c-style language would be cool, but I can see some
notable implementation issues (needing something like an interpreter at
compile time, and running into problems based on the ad-hoc ways I tend to
structure the parse trees).

better would be probably trying to pull off magic with templates, and making
the compiler smart enough to figure what stuff is going on at compile time
and what is going on at run-time (eg: it could expand all the code as if it
were to be done at run-time, and the optimizer would eliminate everything
that can be done at compile time).

still, this could have limits, eg, recursive templates could be a problem as
they would generate a recursive pattern in the parse trees. more hackery
could be done, eg, lazily evaluating templates during optimization. the
result would be that, during optimization, branches that get eliminated
first (eg: if with a constant expression) never get processed, and, thus,
the templates are never evaluated.

or something (likely, c++ compilers do something similar allready, but I
haven't looked into this).

for now, I probably wont add them (if I get to finishing implementing the
language at all...).


>>java also didn't have the idea of stack-allocated/in-place arrays or
>>structures, which was a detractor.
>
> (as much as it pains me to say this) You should take a look at C#. Like
> Java, most things are handled by reference. But it distinguishes between
> stack and heap values, especially for primitive types. When a primitive
> type needs to on the heap, it gets boxed up in a class, like java.
> Anyway,
> I think it might have stack allocated arrays, or at least stack allocated
> tuples.
>

c# lacks any dynamic types (ok, so did java), which are at least sort-of a
requirement for my uses. likewise I am not compelled much to write a c#
compiler anyways, nor do I know of any besides ms's, ...

problem is:
I like dynamic types, so much so that I did my own dynamic type-system and
have been using it with c for quite a while (along with garbage collection,
though I keep overly relying on it, and the gc kicking on can be rather
annoying sometimes).

though one doesn't always (or even often) need dynamic types, there are
cases where they are imo necessary (or at least quite helpful).

but, yeah, any scripting lang I use should support dynamic types, in
particular, 'my' dynamic types. this does limit my options a little.

> The stack allocation is interesting for classes. It would be nice if
> stack
> allocated classes had their destructors called when they go out of scope,
> as
> in C++. A version with reference counting instead of garbage collection
> would also be interesting. I've seen Java programmers jump through hoops
> trying to manage external resources like file-descriptors, with only
> GC finalizers.
>

yes.

java's lack of explicit destruction seems like a problem imo (I had
considered explicit destruction, but more as a 'use with caution' feature).

stack allocated classes were not included in my idea due to syntactic
reasons (lack of explicit pointers). potentially, the language could infer
that an object would never go outside the scope of some function, and thus
make it stack allocated, but I didn't do this. I opted making it explicit,
eg, 'structs'.

alternatively, though, I could make it so that some keyword or something
would make classes reside on the stack.

class Foo extends Bar options pass_by_value {
...
}

ok, this looks like crap. if something like this were done, I might need
something different ('on_stack' looked worse imo).

> Someone needs to add templates to Java or C#: that you have to use
> downcasting to make generic containers is dangerous.

yes, ok.
my idea was that generic containers would be handled by use of variant. as
for classes, variant would allways know that it is a class, and what class.
assignment back to typed variables would incure typechecking though.


templates could be cool, but likely I would change their syntax a little.

template min(x, y)
{
return (x<y)?x:y;
}

vs:
template min<x, y>
{
return (x<y)?x:y;
}

wtf is with those angle brackets anyways?...
who sat around and thought that one was a good idea?
given c++'s design, it is unlikely it was needed to avoid confusing the
compiler, so, I don't get it...

0 new messages