(January 2, 2019 at 3:01 am)FlatAssembler Wrote: So, I'd like to share my first steps in designing programming languages. As some of you know, for the last 11 months or so, I've been developing a program called Arithmetic Expression Compiler. It's written mostly in JavaScript and it converts directives from my own programming language (at first just arithmetic expressions) to FlatAssembler-compatible and i486-compatible (let's pretend it's i486-compatible, I haven't bothered to actually test it on anything else than my 12-year-old PC with 1Ghz Celeron processor) assembly. Recently, using the Duktape framework, I extended it to be able to not just compile single directives, but entire simple programs written in files.
So, here is one of the first programs I've written in the first programming language I've made myself:
You can download the source code of my compiler there, there is a link there to a ZIP-archive containing the source code and instructions on how to compile it using CLANG or GCC (000webhost doesn't allow me to host executable files):Code:;Advanced example: implementing the permutation algorithm.
AsmStart
debug=0
macro pushIntToStack x
{
sub esp,4
fld dword [x]
fistp dword [esp]
}
macro pushPointerToStack x
{
sub esp,4
lea ebx,[x]
mov [esp],ebx
}
macro pushStringToStack x
{
sub esp,4
mov dword [esp],x
}
format PE console
entry start
include 'win32a.inc'
section '.text' code executable
start:
jmp enterNumber$
enterNumber db "Enter a whole number (1 - 1'000'000).",10,0
enterNumber$:
pushStringToStack enterNumber
call [printf]
pushPointerToStack original
jmp floatSign$
floatSign db "%f",0
floatSign$:
pushStringToStack floatSign
call [scanf]
jmp permutationString$
permutationString db "The permutations of its digits are:",10,0
permutationString$:
pushStringToStack permutationString
call [printf]
AsmEnd
numberOfDigits:=0
i:=0
While i<10
countDigits[i]:=0
i:=i+1
EndWhile
While original>0
numberOfDigits:= numberOfDigits + 1
lastDigit:= mod( original , 10 )
countDigits[ lastDigit ]:=countDigits( lastDigit ) + 1
original:= (original - lastDigit) / 10
EndWhile
AsmStart
if debug=1
AsmEnd
i:=0
While i<10
subscript:=4*i
AsmStart
fld dword [subscript]
fistp dword [subscript]
mov ebx,[subscript]
pushIntToStack (countDigits+ebx)
pushStringToStack integerSign
call [printf]
AsmEnd
i:=i+1
EndWhile
AsmStart
pushStringToStack newLineString
call [printf]
AsmEnd
AsmStart
end if
AsmEnd
topOfMyStack:=1
myStack[(numberOfDigits+1)]:=0
While topOfMyStack>0
currentNumberOfDigits:=myStack ( topOfMyStack * ( numberOfDigits + 1 ) )
i:=0
While i<currentNumberOfDigits
currentNumber(i):=myStack ( topOfMyStack * ( numberOfDigits + 1 ) + ( i + 1 ) )
i:=i+1
EndWhile
AsmStart
if debug=1
AsmEnd
i:=0
While i<currentNumberOfDigits
subscript:=i*4
AsmStart
fld dword [subscript]
fistp dword [subscript]
mov ebx,[subscript]
pushIntToStack (currentNumber+ebx)
pushStringToStack integerSign
call [printf]
AsmEnd
i:=i+1
EndWhile
AsmStart
pushStringToStack newLineString
call [printf]
AsmEnd
AsmStart
end if
AsmEnd
topOfMyStack:=topOfMyStack-1
If currentNumberOfDigits=numberOfDigits
i:=0
While i<numberOfDigits
subscript:=i*4
AsmStart
fld dword [subscript]
fistp dword [subscript]
mov ebx,[subscript]
pushIntToStack (currentNumber+ebx)
pushStringToStack integerSign
call [printf]
AsmEnd
i:=i+1
EndWhile
AsmStart
pushStringToStack newLineString
call [printf]
AsmEnd
Else
i:=0
While i<10
counter:=0
j:=0
While j<currentNumberOfDigits
If currentNumber(j)=i
counter:=counter+1
EndIf
j:=j+1
EndWhile
If counter<countDigits(i)
topOfMyStack:=topOfMyStack+1
myStack(topOfMyStack*(numberOfDigits+1)):=currentNumberOfDigits+1
j:=0
While j<currentNumberOfDigits
myStack(topOfMyStack*(numberOfDigits+1)+(j+1)):=currentNumber(j)
j:=j+1
EndWhile
myStack (topOfMyStack * (numberOfDigits + 1) + (j + 1) ) := i
EndIf
i:=i+1
EndWhile
EndIf
EndWhile
AsmStart
invoke system,_pause
invoke exit,0
_pause db "PAUSE",0
integerSign db "%d",0
newLineString db 10,0
section '.rdata' readable writable
original dd ?
result dd ?
lastDigit dd ?
numberOfDigits dd ?
countDigits dd 11 dup(?)
subscript dd ?
myStack dd 1000 dup(?)
topOfMyStack dd ?
counter dd ?
i dd ?
currentNumber dd 11 dup(?)
currentNumberOfDigits dd ?
j dd ?
section '.idata' data readable import
library msvcrt,'msvcrt.dll'
import msvcrt,printf,'printf',system,'system',exit,'exit',scanf,'scanf'
AsmEnd
http://flatassembler.000webhostapp.com/compiler.html
I've designed this programming language to be as easy to integrate with Assembly as possible. The Assembly code C compilers have to produce (trying to declare variables themselves, trying to declare functions themselves...) has to be almost completely rewritten if you are targeting a different assembly language compiler or a different operating system.
However, the solution I've made may be even worse than the problem. The programs written in that programming language are completely non-portable. Also, since my compiler tries to make as few assumptions as possible, it produces way inferior Assembly code than any decent C-compiler would. However, it seems to make no perceptible difference on a what's now a 12-year-old computer (the Assembly code a JavaScript JIT-compiler produces is probably even less optimal). Also, because of the design of my programming language, it often happens that a compiler doesn't catch an error such as using an undeclared variable and outputs syntactically invalid Assembly.
I am also dreaming about making a compiled LISP-like language in which you could write arithmetic expressions in both S-expressions and infix-expressions, but be able to use only S-expressions elsewhere (since they come very handy in string and array-manipulation). However, I probably won't have time for that in foreseeable future.
Designing your own computer language? Are you, like, a genius?