Aros/Developer/Docs/E

From Wikibooks, open books for an open world
Jump to: navigation, search
Navbar for the Aros wikibook
Aros User Docs
Aros User Docs
Aros User FAQs
Aros User Applications
Aros User DOS Shell
Aros/User/AmigaLegacy
Aros Dev Docs
Aros Developer Docs
Porting Software from AmigaOS/SDL
For Zune Beginners
Zune .MUI Classes
For SDL Beginners
Aros Developer BuildSystem
Specific platforms
68k Support
PPC Power Architecture Support
Arm Raspberry Pi Support
Android support
Linux and FreeBSD Support
Windows Mingw and MacOSX Support
Aros x86 Installing
Aros x86 Audio/Video Support
Aros x86 Network Support
Aros x86 Complete System HCL
Aros Storage Support IDE SATA etc
Aros Poseidon USB Support
x86-64 Support
misc
Aros Public License

AmigaE[edit]

Read more here.

Amiga E, or very often simply E, is a programming language created by Wouter van Oortmerssen on the Amiga.

Amiga E is a combination of many features from a number of languages, but follows the original C_Programming and C++, most closely in terms of basic concepts like in the sense that it is fast and weakly typed, and had a rich set of features from procedural, object oriented and functional programming languages.

Amiga E's main benefits are fast compilation (allowing it to be used in place of a scripting language), very readable source code, flexible type system, powerful module system, exception handling (not C++ variant) and object oriented programming.

Contact the AmigaE IRC channel irc.freenode.net at #amigaE



PortablE[edit]

For further information and questions, Portable E has its own forum here. PortablE is an AmigaE compiler, written from scratch in E, and able to compile itself. There is a mailing list for E where you might get some answers.

Read more here.

This is how PortablE works. You write your Amiga E code, use PortablE to translate it into a .cpp file and then use any C++ compiler to compile the file into an executable. I have been using g++ inside AROS. If you want to go to Amiga Classic, you can use PortablE to translate to Amiga E and then move it to Classic where you can use an Amiga E compiler like CreativE.

If PortablE is not already set up for use, you need to set a Stack of at least 100000 to run PortablE. You can set this up by typing in the AROS shell.

stack 100000

You need to do an assign for PEmodules.

Assign PEmodules: VolumeName:PEmodules

You can put Assign commands like this in your user-startup file in AROS so you don’t have to do it everytime. User-startup is in System:S (S drawer).

You also need some Assigns placed in there for g++. The exact Assigns you need can be found in the INSTALL file located in System:Development

So here are the commands I entered on the command line once I had things setup to test a simple program.

PortablE test.e (This gave me a file named test.cpp)
g++ test.cpp -o test (This gave me a file named test to run as an executable)

So then I just typed in the name of my executable at the shell and it ran and printed “Hello, World!”.



Syntax[edit]

Read more here.


Procedures[edit]

A "hello world" program in Amiga E calling another procedure inside

   PROC main()
      DEF z 
      WriteF('Hello, World!\n')
      z:=1
      Another()
   ENDPROC

   PROC another
      DEF y
      y:=2
   ENDPROC



Loops[edit]

       IF x>0
         x:=x+1
         WriteF('Increment: x is now \d\n', x)
       ELSEIF x<0
         x:=x-1
         WriteF('Decrement: x is now \d\n', x)
       ELSE
         WriteF('Zero: x is 0\n')
       ENDIF
       SELECT x
         CASE 0
           WriteF('x is zero\n')
         CASE 10
           WriteF('x is ten\n')
         CASE -2
           WriteF('x is -2\n')
         DEFAULT
           WriteF('x is not zero, ten or -2\n')
       ENDSELECT
     PROC main()
       DEF x
       x:=1
       WHILE x<=100
         WriteF('\d ', x)
         x:=x+1
       ENDWHILE
       WriteF('\n')
     ENDPROC
     PROC main()
       DEF x
       x:=1
       REPEAT
         WriteF('\d ', x)
         x:=x+1
       UNTIL x>100
       WriteF('\n')
     ENDPROC


Summary[edit]

PROC main()
   DEF x,y
   x:=1
   y:=2
   WHILE (x<10) AND (y<10)
      WriteF('x is \d and y is \d\n', x, y)
         x:=x+2
         y:=y+2
   ENDWHILE
ENDPROC
  • The procedure definition.
  • The declaration of the procedure main, with no parameters.
  • The declaration of local variables x and y
  • Initialization of x and y using assignment statements.
  • The WHILE loop
  • The loop check for the WHILE loop using the logical operator AND, the comparison operator <, and parentheses to group the expression.
  • The call to the (built-in) procedure WriteF using parameters. Notice the string, the place holders for numbers, \d, and the linefeed, \n.
  • Assignments to x and y, adding two to their values.
  • The marker for the end of the WHILE loop.
  • The marker for the end of the procedure.

To return a value, replace ENDPROC with ENDPROC value



Data Structures[edit]

Read more about here.


Constants

Numeric

String

Named

Enumeration

Sets



Types[edit]

LONG

PTR

ARRAY

OBJECT

LIST

STRING

Linked Lists



Built-In[edit]

  • Constants - TRUE, FALSE, NIL, ALL, GADGETSIZE, OLDFILE, NEWFILE, STRLEN
  • Variables - arg, wbmessage, stdout, conout, stdrast, dosbase, execbase, gfxbase, intuitionbase,
  • Functions - \c (Number Character) - \d (Number Decimal) - \h (Number Hexadecimal), \s (String String)
  • Functions - \l Left justify in field, \r Right justify in field, \z Set fill character to "0"
  • Functions - WriteF, StringF, Out, Inp, ReadStr, FileLength, SetStdOut,
  • Functions (Intuition) - OpenW, CloseW, OpenS, CloseS, Gadget, Mouse, MouseX, MouseY, WaitIMessage,
  • Functions (Graphics) - Plot, Line, Box, Colour, TextF, SetStdRast, SetTopaz,
  • Functions (Maths) - Abs, Even, Odd, Mod, Rnd, RndQ, Shl, Shr, Long, Int, Char, PutLong, PutInt, PutChar,
  • Functions (System) - New, Dispose, DisposeLink, CleanUp, CtrlC, FreeStack,



Modules[edit]

Exceptions[edit]

Conversion[edit]

The hardest part when moving from BASIC to C, C++ and E is pointers & strings. E & C deal with strings in almost exactly the same way, so there is no great benefit to E there.

AmigaE's treatment of pointers is far simpler than C's, due to C's design. You have to think very carefully about what kind of pointer is required in case a "&" or "*" needs to be added. While with E there is almost never any such worry.

Plus "PTR TO xxx" seems easier to grasp than "xxx*".

Note that there are some good C guides that explain the principles of strings & pointers, using 'box & arrow' diagrams, which you may still find helpful when learning E.


You can just open workbench.library (version 44 or newer required) and call OpenWorkbenchObjectA() as it is documented in autodocs.



Examples[edit]

/* DirList3.e */
MODULE 'std/cGUI', 'std/cPath'

STATIC app_name = 'DirList'

PROC main()
        DEF dirPath:STRING, dir:PTR TO cDir, dirList:PTR TO cDirEntryList
        DEF win:PTR TO cGuiWindow, guiLastFile:PTR TO cGuiTextBox, guiOK
        DEF quit:BOOL, item:PTR TO cGuiItem, entry:PTR TO cGuiFixedListEntry
        
        ->describe our app
        CreateApp(app_name).initDescription('This is a simple PortablE demo.').build()
        
        ->scan directory
        dirPath := ImportDirPath('EnvArc:')
        NEW dir.new()
        IF dir.open(dirPath, /*readOnly*/ TRUE) = FALSE THEN Throw("ERR", 'Failed to open directory')
        dirList := dir.makeEntryList()
        dir.close()
        
        ->build the GUI
        win := CreateGuiWindow(app_name)
        win.beginGroupVertical()
                win.addTextBox('').setState('Below is a list of all the files inside EnvArc:')
                
                win.beginFixedList().initSelectableEntries(/*multiSelect*/ TRUE)
                        ->step through each file
                        IF dirList.gotoFirst(/*any0file1dir2*/ 1)
                                REPEAT
                                        ->add line for file
                                        win.addFixedListEntry(dirList.infoName())
                                UNTIL dirList.gotoNext(1) = FALSE
                        ENDIF
                win.endFixedList()
                
                guiLastFile := win.addTextBox('The last ticked file:')
                
                guiOK := win.addButton('OK')
                
        win.endGroup()
        win.build()
        
        ->handle user interaction with GUI
        quit := FALSE
        REPEAT
                item := WaitForChangedGuiItem()
                IF item = NIL
                        IF win.getCloseRequest() THEN quit := TRUE
                        
                ELSE IF item = guiOK
                        quit := TRUE
                        
                ELSE IF item.IsOfClassType(TYPEOF cGuiFixedListEntry)
                        entry := item::cGuiFixedListEntry
                        IF entry.getState()
                                ->(a file was ticked) so tell user which file they just ticked
                                guiLastFile.setState(entry.infoLabel())
                        ENDIF
                ENDIF
        UNTIL quit
        
        win.close()
FINALLY
        PrintException()
        END dirPath, dir
ENDPROC





-> Shared MUI Custom Class Skeleton. Needs minimum ECX 2.x

OPT PREPROCESS

#define CLASS_NAME 'mytest.mcc'
#define CLASS_VERSION 1
#define CLASS_REVISION 0
#define CLASS_IDSTRING 'mytest.mcc by me'

->#define ONLYGLOBAL
->#define INFOCLASS

#ifdef __MORPHOS__
OPT EXENAME = CLASS_NAME + '.elf'
#else
OPT EXENAME = CLASS_NAME
#endif

#define SUPERCLASS MUIC_Area
->#define SUPERCLASSP

-> Let ECX create a convenient multi base library for us
LIBRARY CLASS_NAME, CLASS_VERSION, CLASS_REVISION, CLASS_IDSTRING IS
mcc_query(D0)


#define DoMethodA(obj,attrs) doMethodA(obj,attrs)
#define DoSuperMethodA(class,obj,attrs) doSuperMethodA(class,obj,attrs)
#define CoerceMethodA(class,obj,attrs) coerceMethodA(class,obj,attrs)

-> handy..
#ifdef DEBUG
   #define DEBUGF(str,...) DebugF(str,...)
#else
   #define DEBUGF(str,...)
#endif


MODULE  'amigalib/boopsi'

MODULE  'muimaster',
        'libraries/mui',
        'libraries/muip',
        'mui/muicustomclass'

MODULE  'intuition/intuition',
        'intuition/classes',
        'intuition/classusr'

MODULE  'exec/libraries',
        'exec/nodes',
        'exec/memory'

MODULE  'utility',
        'utility/tagitem',
        'utility/hooks'


OBJECT classdata
ENDOBJECT

OBJECT classdatap
ENDOBJECT


STATIC g_usedclasses=[NIL]
STATIC g_usedclassesp=[NIL]
STATIC g_shorthelp = ''

DEF g_prefsimageobject=NIL
DEF g_thisclass=NIL:PTR TO mui_customclass
DEF g_thisclassp=NIL:PTR TO mui_customclass

PROC main() HANDLE

   IFN muimasterbase := OpenLibrary(MUIMASTER_NAME,MUIMASTER_VMIN) THEN
      Throw("LIB", MUIMASTER_NAME)

   IFN utilitybase := OpenLibrary('utility.library',39) THEN
      Throw("LIB", 'utility.library')

   #ifdef SUPERCLASS
   IFN g_thisclass := eMui_CreateCustomClass(librarybase,SUPERCLASS,NIL,
                     SIZEOF classdata,{classDispatcher})
      Raise("CMCC")
   ENDIF
   #endif

   #ifdef SUPERCLASSP
   IFN g_thisclassp := eMui_CreateCustomClass(librarybase,SUPERCLASSP,NIL,
                     SIZEOF classdatap,{classDispatcherP})
      Raise("CMCC")
   ENDIF
   #endif

EXCEPT

   DebugF('mcc open() failed: ')

   SELECT exception
   CASE "LIB"   ; DebugF('Could not open library "\s"\n', exceptioninfo)
   CASE "CMCC"  ; DebugF('Could not create mui custom class\n')
   DEFAULT      ; DebugF('Unknown exception $\h\n', exception)
   ENDSELECT

   close()

   RETURN NIL -> make OpenLibrary() fail.

ENDPROC TRUE


PROC close()

   IF g_thisclassp THEN Mui_DeleteCustomClass(g_thisclassp)
   IF g_thisclass THEN Mui_DeleteCustomClass(g_thisclass)

   CloseLibrary(utilitybase)
   CloseLibrary(muimasterbase)

ENDPROC

-> the special fuction needed for any MCC
PROC mcc_query(which)
   SELECT which
   CASE 0
      RETURN g_thisclass
   CASE 1
      RETURN g_thisclassp
   CASE 2
      RETURN g_prefsimageobject
   CASE 3
      #ifdef ONLYGLOBAL
      RETURN TRUE
      #else
      RETURN FALSE
      #endif
   CASE 4
      #ifdef INFOCLASS
      RETURN TRUE
      #else
      RETURN FALSE
      #endif
   CASE 5
      RETURN g_usedclasses
   CASE 6
      RETURN g_usedclassesp
   CASE 7
      RETURN g_shorthelp
   ENDSELECT
ENDPROC NIL

#ifdef SUPERCLASS
PROC classDispatcher(cl:PTR TO iclass, obj:PTR TO object, msg:PTR TO opset)
   SELECT msg.methodid
->   CASE OM_NEW          ;  RETURN classNew      (cl,obj,msg)
->   CASE OM_DISPOSE      ;  RETURN classDispose  (cl,obj,msg)
->   CASE MUIM_AskMinMax  ;  RETURN classAskMinMax(cl,obj,msg)
->   CASE MUIM_Show       ;  RETURN classShow(cl, obj, msg)
->   CASE MUIM_Hide       ;  RETURN classHide(cl, obj, msg)
->   CASE OM_SET          ;  RETURN classSet(cl,obj,msg)
->   CASE OM_GET          ;  RETURN classGet(cl,obj,msg)
   ENDSELECT
ENDPROC DoSuperMethodA(cl,obj,msg)
#endif

#ifdef SUPERCLASSP
PROC classDispatcherP(cl:PTR TO iclass, obj:PTR TO object, msg:PTR TO opset)
ENDPROC
#endif

PROC classNew(cl:PTR TO iclass,obj:PTR TO object,msg:PTR TO opset)
   DEF data:PTR TO classdata

   IFN obj := DoSuperMethodA(cl,obj,msg) THEN RETURN 0

   data := INST_DATA(cl,obj)

ENDPROC obj

PROC classDispose(cl:PTR TO iclass,obj:PTR TO object,msg:PTR TO msg)
   DEF data:PTR TO classdata

   data := INST_DATA(cl,obj)

ENDPROC DoSuperMethodA(cl,obj,msg)

PROC classSet(cl:PTR TO iclass,obj:PTR TO object,msg:PTR TO opset)
   DEF data:REG PTR TO classdata, tags:PTR TO tagitem, tag:REG PTR TO tagitem

   data := INST_DATA(cl,obj)

   tags := msg.attrlist

   WHILE tag := NextTagItem({tags})
      SELECT tag.tag
      ->CASE MUIA_Xxx_Yyy
         ->data.xxxyyy := tag.data
      DEFAULT
      ENDSELECT
   ENDWHILE
ENDPROC DoSuperMethodA(cl,obj,msg)

PROC classGet(cl:PTR TO iclass,obj:PTR TO object,msg:PTR TO opget)
   DEF data:PTR TO classdata

   data := INST_DATA(cl,obj)

   SELECT msg.attrid
   ->CASE MUIA_Xxx_Yzz
   ->  PutLong(msg.storage,data.xxxyyy)
   ->  RETURN MUI_TRUE
   ENDSELECT

ENDPROC DoSuperMethodA(cl,obj,msg)

PROC classAskMinMax(cl:PTR TO iclass,obj:PTR TO object,msg:PTR TO muip_askminmax)
   DEF data:PTR TO classdata, mi:PTR TO mui_minmax

   DoSuperMethodA(cl,obj,msg)

   data := INST_DATA(cl,obj)

   mi := msg.minmaxinfo

   mi.minwidth  += 16
   mi.minheight += 16
   mi.defwidth  += 128
   mi.defheight += 128
   mi.maxwidth  += MUI_MAXMAX
   mi.maxheight += MUI_MAXMAX

ENDPROC 0

PROC classShow(cl:PTR TO iclass, obj:PTR TO object, msg:PTR TO opset)
   DEF data:PTR TO classdata

   IFN DoSuperMethodA(cl,obj,msg) THEN RETURN FALSE

   data := INST_DATA(cl, obj)

ENDPROC MUI_TRUE

PROC classHide(cl:PTR TO iclass, obj:PTR TO object, msg:PTR TO opset)
   DEF data:PTR TO classdata

   data := INST_DATA(cl, obj)

ENDPROC DoSuperMethodA(cl, obj, msg)






Reference[edit]

AmigaE works well and integrates with Assembly well also. Just don't go writing shared libraries with it since there are design flaws with the library mode. Also, if you plan on using multiple return codes, keep them in the same source as your application code because the module generation doesn't work right with multiple return codes. Lastly, don't nest the function form of the IF keyword (the AmigaE equivalent of the ? : operators in C). Those are all of the bugs I can think of in the compiler.