Pinky

Pinky language

Pinky is a structured programming language. It is statically typed. The language was designed to be simple, without bells and whistles, so that it's easy to learn. Pinky code is compiled to Jamcode.

Program structure

The only structural requirement for a Pinky program, is that it includes an entry-point procedure called "run". The run procedure should accept no arguments and should return nothing.

A Pinky program is typically organized like so:

  1. Types
  2. Native structures
  3. Native procedures
  4. Structures
  5. Global variables
  6. Procedures
  7. Entry-point

Primitive types

Top-level operations

SyntaxDescription
type Graphics
Declare a native type
struct Foo
  a : int
  b : int
end
Define a structure
x : int
Declare a global variable
x = 123
Declare/initialize a global variable or set an already declared variable
proc sum(a:int, b:int) : int
  return a + b          
end
Define a procedure

Procedure-level operations

SyntaxDescription
x : int
Declare a variable
x = 123
Declare/initialize a variable or set an already declared variable
x = 1 + 2 - 2 * 4 / 2
Perform integer arithmetic
x = 1 <  2
x = 1 <= 2
x = 2 >  1
x = 2 >= 1
x = 2 == 2
x = 2 != 1
Perform integer comparisons
x = xor(2, 2)
x = or(0, 1)
x = and(1, 1)
Perform bitwise operations
x = false & true | true
Perform boolean logic
foo = new Foo
Create structure (not recommended; below method is favored)
foo = {1, 2} as Foo
Create initialized structure
bar = new int[4]
Create array
if true then
  print("1")
elif false then
  print("2")
else
  print("3")
end
Control code flow
while true do
  print(".")
end
Loop forever
t = step(10)
print("1")
after;
t = step(10)
print("2")
after;
print("3")
Stateful procedure (print number 1 the first 10 times the procedure is called, then print 2 the 10 times it's called after that, then finally, print 3 for every call after that.

Example: Hello, World!

proc run()  
  print("Hello, World!")
end

Example: standard-library unit test

proc run()  
  print("Testing types and operators...")
  nop()  
  assert(true)
  assert(!false)
  assert(true&true)
  assert(false|true)
  assert(1==1)
  assert(1!=2)
  assert(1<=1)
  assert(1>=1)
  assert(2>1)
  assert(1<2)
  assert(2-1==1)      
  assert(1+1==2)
  assert(2*3==6)
  assert(12/4==3)    
  assert(6+-2==4)
  assert(6+4-2+-1*2/(4-2)==7)
  assert(gettype(null)==TYPE_NULL)
  assert(gettype(237)==TYPE_INT)
  assert(gettype(9872)==TYPE_INT)
  assert(gettype("foo")==TYPE_STR)
  assert(gettype(run)==TYPE_PROC)
  assert(gettype({} as int[])==TYPE_ARRAY)
  sleep(1)
  
  print("Testing core built-ins..")    
  assert(is(true,true))
  assert(!is(true,false))
  seed(123)
  assert(rand(0,100)==11)
  seed(567)
  assert(rand(0,100)==81)
  assert(time()>0)
  
  print("Testing integer built-ins...")      
  assert(and(2,1)==0)
  assert(and(2,3)==2)  
  assert(or(2,1)==3)
  assert(or(2,2)==2)
  assert(xor(3,1)==2)
  assert(xor(2,2)==0)
  assert(xor(2,0)==2)
  assert(shl(1,1)==2)
  assert(shr(2,1)==1)
  assert(mod(10,2)==0)
  assert(mod(9,2)==1)
  assert(mod(-8,5)==2)
  assert(mod(-5,5)==0)
  assert(mod(-4,5)==1)
  assert(min(2,3)==2)
  assert(min(3,2)==2)          
  assert(max(2,3)==3)
  assert(max(3,2)==3)
  assert(abs(-3)==3)
  assert(abs(3)==3)
  assert(icmp(3,3)==0)
  assert(icmp(3,1)==1)
  assert(icmp(3,4)==-1)
  
  print("Testing fixed-point built-ins...")        
  assert(1.0==1.0)
  assert(3.0/1.5==2.0)
  assert(2.0*1.5==3.0)
  assert(fmod(9.0,2.0)==1.0)
  assert(fmin(2.0,3.0)==2.0)
  assert(fmin(3.0,2.0)==2.0)
  assert(fmax(2.0,3.0)==3.0)
  assert(fmax(3.0,2.0)==3.0)
  assert(fabs(-3.0)==3.0)
  assert(fabs(3.0)==3.0)
  assert(pow(2.0,2.0)==4.0)
  assert(sqrt(16.0)==4.0)
  assert(floor(1.0)==1.0)
  assert(floor(1.5)==1.0)
  assert(floor(1.9999)==1.0)
  assert(floor(-1.5)==-2.0)  
  assert(ceil(1.0)==1.0)
  assert(ceil(1.5)==2.0)
  assert(ceil(1.9999)==2.0)
  assert(ceil(-1.0)==-1.0)
  assert(ceil(-1.5)==-1.0)
  assert(frac(1.5)==0.5)
  assert(frac(1.0)==0.0)
  assert(fp(1, 0xffff)==1.999999999)
  assert(ftoi(1.0)==1)
  assert(ftoi(-3.5)==-4)

  print("Testing fixed-point trigonometric built-ins...")
  assert(hypot(2.0, 3.0)==3.605551275463989)
  assert(sin(0.0)==0.0)
  assert(sin(PI/2)==0.999984741211)
  assert(cos(0.0)==1.0)
  assert(cos(PI/2)==0.0)
  assert(tan(0.0)==0.0)
  assert(tan(PI*5.0/12.0)==3.73194885254)
  
  print("Testing string built-ins...")        
  assert(scmp("foo","foo")==0)
  assert(scmp("foo","bar")!=0)    
  assert(scmp(ftos(3.5),"3.5")==0)
  assert(scmp(ftos(3.0),"3.0")==0)
  assert(scmp(ftos(0.0),"0.0")==0)    
  assert(scmp(itos(123),"123")==0)
  assert(scmp(concat("foo","bar"),"foobar")==0)
  assert(scmp(join(",",{"foo","bar"}),"foo,bar")==0)
  assert(scmp(chr(32)," ")==0)
  assert(ord(" ", 0)==32)
  assert(slen("yellow")==6)
  assert(stoi("123")==123)
  assert(scmp(decodeb64("Zm9vYmFy"),"foobar")==0)
  assert(scmp(b64("hello world"),"aGVsbG8gd29ybGQ=")==0)

  print("Testing array built-ins...")
  x = {4,5,6} as int[]
  y = {4,5,6,7,8,9} as int[]
  assert(alen(x)==3)
  assert(alen(y)==6)    
  assert(x[1]==5)
  yy = slice(y, 2, 3)
  assert(alen(yy)==3)
  assert(yy[0]==6)
  assert(yy[1]==7)
  assert(yy[2]==8)
  xx = reverse(x) as int[]
  assert(xx[0]==6)
  assert(xx[1]==5)
  assert(xx[2]==4)
  yy = slice(y, 0, alen(y))
  fill(yy, 8, 1, 4)
  assert(yy[0]==4)
  assert(yy[1]==8)
  assert(yy[2]==8)
  assert(yy[3]==8)
  assert(yy[4]==8)
  assert(yy[5]==9)
  copy(yy, xx, 2, 2)
  assert(yy[0]==4)
  assert(yy[1]==8)
  assert(yy[2]==6)
  assert(yy[3]==5)
  assert(yy[4]==8)
  assert(yy[5]==9)
  sort(yy, icmp)
  assert(yy[0]==4)
  assert(yy[1]==5)
  assert(yy[2]==6)
  assert(yy[3]==8)
  assert(yy[4]==8)
  assert(yy[5]==9)
  
  print("Testing blob built-ins...")
  my_data : blob
  my_data = blob(10)
  assert(!is(my_data, null))
  assert(blen(my_data)==10)
  set(my_data, 0, 7)
  set(my_data, 1, 11)
  set(my_data, 9, 45)
  assert(get(my_data, 0)==7)
  assert(get(my_data, 2)==0)  
  assert(get(my_data, 1)==11)
  assert(get(my_data, 9)==45)
  data_123 = blob(3)
  sets(data_123,0,"123",3)
  assert(get(data_123, 0)==ord("1",0))
  assert(get(data_123, 1)==ord("2",0))
  assert(get(data_123, 2)==ord("3",0))
  assert(blen(data_123)==3)
  assert(scmp(gets(data_123,1,2), "23")==0)
  sets(data_123,1,"89",2)
  assert(get(data_123, 0)==ord("1",0))
  assert(get(data_123, 1)==ord("8",0))  
  assert(get(data_123, 2)==ord("9",0))
  assert(blen(data_123)==3)  
  bsave(my_data, "foo")
  my_data2 = bload("foo")
  assert(blen(my_data2)==blen(my_data))
  assert(get(my_data2, 0)==7)
  assert(get(my_data2, 2)==0)  
  assert(get(my_data2, 1)==11)
  assert(get(my_data2, 9)==45)

  print("Testing array access syntax...")
  list_of_x = {x, xx, x} as (int[])[]
  assert(list_of_x[0][0]==4)
  assert(list_of_x[0][1]==5)
  assert(list_of_x[0][2]==6)
  assert(list_of_x[1][0]==6)
  assert(list_of_x[1][1]==5)
  assert(list_of_x[1][2]==4)
  assert(list_of_x[2][0]==4)
  assert(list_of_x[2][1]==5)
  assert(list_of_x[2][2]==6)
  assert(test_array()[0]==1)
  assert(test_array()[1]==2)
  assert(test_array()[2]==3)
  test_array_2(x)[0] = 683
  assert(x[0]==683)
  
  print("All tests passed!")
end