+ Reply to Thread
Results 1 to 9 of 9

Thread: BulkOS 3 - now with 10% more bulk!

  1. #1
    Mario, hard at work Filipe's Avatar
    Join Date
    Jun 2007
    Location
    Portugal - Lisbon
    Posts
    401
    Blog Entries
    1

    Default BulkOS 3 - now with 10% more bulk!

    (note to mods: I just noticed my old thread is still floating around, if this is a problem, please remove the old topic and not this one)

    Current version: 3.2

    New features:
    • Cleaned up the code, but kept the bulky goodness inside.
    • More freedom when using or defining values, support for memory pointers.
    • Jumps and conditional jumps, improved program flow by 10000%.
    • Applications can now get user input, and even bind keys. Games, anyone?
    • Easier to use all around, simplified alot of functions that were needlessly complicated.
    All that and much more (including the download), read all about it on the website.

    (it's on a seperate website because of the sheer amound of content needed, it'd be a headache to edit it all into a post)





    While E2 code is open source and free by nature, I think it's worth mentioning that you are free to edit and redistribute your own modifications to this script. You don't even have to credit me (even tho that'd be a nice touch).

    [highlight=e2]@name Bulk OS 31
    @inputs Char [S Out]:wirelink Reset
    @outputs Screen:string
    # Generic:
    @persist [Saved String Prefix FName Function File Sep]:string D:array CBlock IBlock WAIT [CMPA CMPB]:string WAITFORINPUT Scroll
    # Stack:
    @persist [Stack M UI BulkData]:array T:table
    @trigger
    @model models/cheeze/wires/cpu2.mdl

    # Reset switch:
    if(Reset & ~Reset & !IBlock) { reset() }
    if(first() | duped()) {
    # Input screen default:
    Prefix = Screen = "\n\n /> "
    File = "/bulkos/bulkos.txt"
    Sep = ";"
    Scroll = 1
    # Welcome message:
    DushString(":444:Welcome to BulkOS 3.2")
    DushString(":444:"+"=":repeat(30))
    }
    if(!~Char) {
    # Data update:
    T["time",string] = time("hour")+":"+time("min")+":"+time("sec")
    T["date",string] = time("day")+"/"+time("month")+"/"+time("year")
    T["curtime",number] = curtime()
    T["lastsaid",string] = lastSaid()
    }

    # Keyboard input:
    if(changed(Char) & Char>0 & !IBlock) {
    # Numpad support:
    if(Char>=128 & Char<=137) {
    Char = Char-128
    Key = Char:toString()
    }
    elseif(Char == 138 ) {
    Key = "/"
    }
    else{ Key = toChar(Char)}
    # Program override:
    if(UI[Char,string]!="") {
    StackushString(UI[Char,string])
    }
    # Backspace:
    elseif(Char == 127 & String:length()>=0) {
    String = String:left(String:length()-1)
    }
    # Shift key
    elseif(Char == 154) { # ignore.
    }
    # Print stack data (might move to program override?):
    elseif(Char == 149) {
    if(Stack:count()>0) {
    DushString(":444: Printing stack contents:")
    DushString(":444:"+"=":repeat(30))
    for(I=1,Stack:count()) { DushString(":136:"+Stack[I,string]) }
    DushString(":333:"+"=":repeat(30))
    }
    else{ DushString(":900:Action stack is empty!") }
    }
    # ENTER key
    elseif(Char == 13) {
    # Function editor:
    if(FName!="") {
    String = String:trim()
    if(String=="exit" | String=="end") {
    T[FName,string] = Function:trim()
    DushString("=":repeat(30)) DushString(":990:Saved function '"+FName+"'.")
    FName = Function = ""
    }
    else{
    DushString(":999:"+String+Sep)
    Function = Function+String+Sep
    }
    }
    else{
    Saved = String StackushString(String)
    T["input",string] = String
    }
    # Clear string:
    String = ""
    # Stop waiting for input:
    WAITFORINPUT = 0
    }
    else{ String = String + Key T["string",string] = String}
    # Update screen:
    Screen = Prefix+String
    }

    # The mighty stack processor:
    if(clk("readstack")) {
    A = Stack[1,string]:trim() Stack:remove(1)
    PrePro = A:explode(" ")
    Com = PrePro[1,string] PrePro:remove(1)
    for(I=1,PrePro:count()) {
    V = PrePro[I,string]
    IsMemRef = V:index(1) == "#"
    Clean = V:replace("#","")
    IsAddr = T[Clean,string] != "" | T[Clean,number]!=0
    if(IsAddr & IsMemRef) {
    Str = T[Clean,string]
    Num = T[Clean,number]
    if(Str!="") {
    PrePro[I,string] = Str
    }
    elseif(Num!=0) {
    PrePro[I,number] = Num
    }
    }
    elseif(IsMemRef) {
    Str = M[Clean:toNumber(),string]
    Num = M[Clean:toNumber(),number]
    if(Str!="") {
    PrePro[I,string] = Str
    }
    elseif(Num!=0) {
    PrePro[I,number] = Num
    }
    }
    }
    All = PrePro:concat(" ")
    Target = PrePro[1,string]:toNumber()
    TargetS = PrePro[1,string]

    # Prt:
    if(Com == "prt" | Com == "print" | Com == "echo") {
    DushString(All)
    }
    # Lock
    if(Com == "lock") {
    IBlock = clamp(Target,0,1)
    }
    # Line/Div
    if(Com == "line") {
    S[2038] = 1
    S:writeString(" ":repeat(30),0,16,999,!Target*555+Target)
    }
    # Com quit:
    elseif(Com == "exit" | Com == "break" | Com == "quit") {
    Stack = array() DushString(":900: Ended program(s).")
    }
    # Wait:
    elseif(Com == "wait" | Com == "hold") {
    if(TargetS == "input") { WAITFORINPUT = 1 }
    else{WAIT = Target}
    }
    # Reset:
    elseif(Com == "reset" | Com == "restart") {
    reset()
    }
    # Beep!(suck it, Fizyk!):
    elseif(Com == "beep" | Com == "boop") {
    soundPlay(1,0.3,"synth/tri.wav") Pitch = PrePro[1,string]:toNumber()
    Pitch = (!Pitch*100)+Pitch soundPitch(1,Pitch)
    }
    # toByte
    elseif(Com == "tobyte") {
    M[Target,number] = toByte(PrePro[2,string]:left(1))
    }
    elseif(Com == "tochar") {
    M[Target,string] = toChar(PrePro[2,string]:left(1):toNumber())
    }
    # Draw:
    elseif(Com == "cs") {
    if(TargetS == "line") {
    Clamp = clamp(PrePro[3,string]:toNumber(),!PrePro[3,string]:toNumber()*999,999)
    S:writeString(" ":repeat(30),0,PrePro[2,string]:toNumber(),Clamp,Clamp)
    }
    elseif(TargetS == "scroll" | TargetS == "scr") {
    Scroll = clamp(PrePro[2,string]:toNumber(),0,1)
    }
    else{
    Data = PrePro[2,string]:toNumber() S[Target] = Data
    }
    }
    # Clear(console) (shortcut):
    elseif(Com == "clear" | Com == "clr") {
    S[2041] = 1
    }
    # Function editor:
    elseif(Com == "func" | Com == "file" | Com == "function") {
    FName = TargetS:trim()
    DushString("=":repeat(30)) DushString(":990:Editing function '"+FName+"'")

    }
    # Run!:
    elseif(Com == "run" | Com == "program" | Com == "call" | Com == "do") {
    BulkData = All:explode(Sep)
    for(I=1,BulkData:count()) { StackushString(BulkData[I,string]:trim()) }
    }
    # UI bind/unbind:
    elseif(Com == "bind") {
    PrePro:remove(1) DataS = PrePro:concat(" ")
    UI[Target,string] = DataS
    }
    elseif(Com == "unbind") {
    if(TargetS == "all") { UI = array() }
    else{UI[Target,string] = ""}
    }
    # JUMP!
    elseif(Com == "jmp" | Com == "jump") {
    if(BulkData:count()>0) {
    Label = TargetS+":" Stack = array()
    for(I=1,BulkData:count()) {
    if(BulkData[I,string]:trim() == Label:trim()) { Found = I break }
    }
    for(I = Found,BulkData:count()) {
    StackushString(BulkData[I,string])
    }
    }
    else{ DushString(":900:No data to jump to!") }
    }
    # CMP: (oh boy..)
    elseif(Com == "cmp" | Com == "compare") {
    CMPA = PrePro[1,string] CMPB = PrePro[2,string]
    }
    # Conditionals:
    elseif(Com == "je" | Com == "equal") {
    Cmp = CMPA == CMPB Label = TargetS
    if(Cmp) { Stack = array() StackushString("jmp "+Label) }
    }
    elseif(Com == "jne" | Com == "notequal") {
    Cmp = CMPA != CMPB Label = TargetS
    if(Cmp) { Stack = array() StackushString("jmp "+Label) }
    }
    elseif(Com == "jle" | Com == "lessqual") {
    Cmp = CMPA:toNumber() <= CMPB:toNumber() Label = TargetS
    if(Cmp) { Stack = array() StackushString("jmp "+Label) }
    }
    elseif(Com == "jle" | Com == "less") {
    Cmp = CMPA:toNumber() < CMPB:toNumber() Label = TargetS
    if(Cmp) { Stack = array() StackushString("jmp "+Label) }
    }
    elseif(Com == "jge" | Com == "greaterequal") {
    Cmp = CMPA:toNumber() >= CMPB:toNumber() Label = TargetS
    if(Cmp) { Stack = array() StackushString("jmp "+Label) }
    }
    elseif(Com == "jg" | Com == "greater") {
    Cmp = CMPA:toNumber() > CMPB:toNumber() Label = TargetS
    if(Cmp) { Stack = array() StackushString("jmp "+Label) }
    }

    # Mov:
    elseif(Com == "movnum") {
    DataN = PrePro[2,string]:toNumber()
    M[Target,number] = DataN
    }
    elseif(Com == "movstr") {
    PrePro:remove(1) DataS = PrePro:concat(" ")
    M[Target,string] = DataS
    }
    # Put/Get:
    elseif(Com == "put") {
    PrePro:remove(1) DataS = PrePro:concat(" ")
    T[TargetS,string] = DataS
    }
    elseif(Com == "get") {
    PrePro:remove(1)
    M[Target,string] = T[PrePro:concat(" "),string]
    }
    # External mem:
    elseif(Com == "out") {
    Out[Target] = PrePro[2,string]:toNumber()
    }
    elseif(Com == "in") {
    M[Target,number] = Out[PrePro[2,string]:toNumber()]
    }
    # Math:
    elseif(Com == "rand") {
    RandA = PrePro[2,string]:toNumber()
    RandB = PrePro[3,string]:toNumber()
    Random = randint(RandA,RandB)
    M[Target,number] = Random
    }
    elseif(Com == "add") {
    M[Target,number] = M[Target,number] + PrePro[2,string]:toNumber()
    }
    elseif(Com == "sub") {
    M[Target,number] = M[Target,number] - PrePro[2,string]:toNumber()
    }
    elseif(Com == "div") {
    M[Target,number] = M[Target,number] / PrePro[2,string]:toNumber()
    }
    elseif(Com == "mul") {
    M[Target,number] = M[Target,number] * PrePro[2,string]:toNumber()
    }
    elseif(Com == "inc") {
    M[Target,number] = M[Target,number] + 1
    }
    elseif(Com == "dec") {
    M[Target,number] = M[Target,number] - 1
    }
    # String functions:
    elseif(Com == "concat") {
    PrePro:remove(1)
    M[Target,string] = M[Target,string] + PrePro:concat(" ")
    }
    elseif(Com == "strlen") {
    PrePro:remove(1)
    M[Target,number] = PrePro:concat(" "):length()
    }
    elseif(Com == "upper") {
    PrePro:remove(1)
    M[Target,string] = PrePro:concat(" "):upper()
    }
    elseif(Com == "lower") {
    PrePro:remove(1)
    M[Target,string] = PrePro:concat(" "):lower()
    }
    elseif(Com == "trim") {
    PrePro:remove(1)
    M[Target,string] = PrePro:concat(" "):trim()
    }
    elseif(Com == "say") {
    concmd("say [bulkOS]: "+All)
    }
    elseif(Com == "explode") {
    PrePro:remove(1)
    Bulk = PrePro:concat(" "):explode("")
    for(I=Target,Bulk:count()) {
    M[I,string] = Bulk[I,string]
    }
    }
    # File functions:
    elseif(Com == "savedb") {
    SAVE = 1
    }
    elseif(Com == "load") {
    File = "/bulkos/"+TargetS timer("reload",300)
    }
    elseif(Com == "write") {
    WriteTo = "/bulkos/"+TargetS
    PrePro:remove(1)
    fileWrite(WriteTo,PrePro:concat(" "))
    }
    elseif(Com == "append") {
    WriteTo = "/bulkos/"+TargetS
    PrePro:remove(1)
    fileAppend(WriteTo,PrePro:concat(" "))
    }
    elseif(Com == "remove") {
    WriteTo = "/bulkos/"+TargetS
    fileRemove(WriteTo)
    }
    elseif(Com == "pushmem") {
    T["mem",string] = glonEncode(M)
    }
    elseif(Com == "pullmem") {
    M = glonDecode(T["mem",string])
    }

    }

    # File handler:
    if(clk("reload") | first() | duped() | fileClk()) {
    if(!fileLoaded(File)) { fileLoad(File) runOnFile(1) }
    else{
    if(File == "/bulkos/bulkos.txt") {
    T = glonDecodeTable(fileRead(File))
    StackushString("run "+T["startup",string])
    }
    else{
    T["file",string] = fileRead(File)
    T["fname",string] = File:replace("/bulkos/",""):trim()
    }
    }
    }

    if(SAVE) {
    # This 'file' juggling bit is to avoid a huge file being saved into the DB inside it's slot.
    Loaded = T["file",string] T["file",string] = ""
    fileWrite("/bulkos/bulkos.txt",glonEncode(T))
    T["file",string] = Loaded SAVE = 0
    }

    # Stack delay handler:
    if(Stack:count()>0) {
    # Delay is capped to 120 seconds by default.
    Time = clamp(WAIT,5,120000) WAIT = 0
    if(!WAITFORINPUT) { timer("readstack",Time) }
    }
    # Console print:
    while(D:count()>0 & !CBlock) {
    Print = D[1,string]
    if(Print:index(1) == ":" & Print:index(5) == ":") {
    Color = Print:sub(2,4):toNumber()
    Print = Print:right(Print:length()-5):trim()
    }
    else{ Color = 999 }
    Lines = ceil(Print:length()/30)
    for(I=0,!Lines+Lines-1) {
    S:writeString(Print:sub(I*31):trim(),0,17,Color,0) D:remove(1)
    S[2038] = Scroll
    }
    }
    [/highlight]

    Faron: the highlighting is broken again, notice the hash in the tables?
    Last edited by Filipe; 01-28-2010 at 04:37 AM.
    beep boop

  2. #2
    Wire Sofaking N00bDud3's Avatar
    Join Date
    Jul 2009
    Location
    Error: Unknown Location
    Posts
    1,252

    Default Re: BulkOS 3 - now with 10% more bulk!

    Nice work! I really like this E2 computer.
    I have been coding an OS recently, and I am using an assembly like language too, as it is easier to parse.



  3. #3
    billywitchdoctor.com Schilcote's Avatar
    Join Date
    Jan 2009
    Location
    There.
    Posts
    2,006

    Default Re: BulkOS 3 - now with 10% more bulk!

    It'd be nice if we could use BulkOS as a basic platform for building more complex OSes...


    [19:16:47]Client "rcdraco" spawned in server
    [19:17:10]rcdraco: hamburgertime
    [19:18:04]rcdraco was killed by worldspawn
    [19:21:50]Dropped "rcdraco" from server

  4. #4
    Mario, hard at work Filipe's Avatar
    Join Date
    Jun 2007
    Location
    Portugal - Lisbon
    Posts
    401
    Blog Entries
    1

    Default Re: BulkOS 3 - now with 10% more bulk!

    Quote Originally Posted by Schilcote View Post
    It'd be nice if we could use BulkOS as a basic platform for building more complex OSes...
    It's not impossible. I'm writing a banking system in bulkcode that sits on top of the OS, but sets up proxies for all the functions. The banking system is loaded on startup and completely overtakes all functions, and presents a neat ordered list with all the options:

    1. View user details.
    2. Create user account.
    3. Delete user account.
    4. Load data file.
    5. Exit and restart with BulkOS. <- unloads the system from the startup, drops it in #banking, saves the db and calls a restart.

    I simply input a number (1/5) and the script handles all the heavy lifting.
    While it's not easy, and definetly not very functional, you CAN write another custom language on top of the existing bulkcode (yo dawg...), and just like I'm doing, the heavy lifting can be offset to a script running in the background over the main OS layer.

    But honestly, the bulkOS name isn't just an attempt at sounding cute, it really fits it. At full speed, performing 5 or 6 operations per second, the E2 shoots up to 1200 ops/s, this is because all the code is parsed on run-time. For the next version I might try coming up with a simple compiler, but I have to look into it, as I don't want to give up on BulkOS's freedom when it comes to code writing (right now you can store code in strings, load it mid-code, heck, you can create a script that edits itself as you go along).
    Last edited by Filipe; 01-28-2010 at 04:47 AM.
    beep boop

  5. #5
    Wire Sofaking Azrael's Avatar
    Join Date
    Aug 2007
    Posts
    1,946

    Default Re: BulkOS 3 - now with 10% more bulk!

    It would be nice if it was compiled, and there was a command to invoke the compiler at runtime on a specific string.

  6. #6
    Wire Sofaking ShadowBrain's Avatar
    Join Date
    Oct 2008
    Location
    Where you live.
    Posts
    910

    Default Re: BulkOS 3 - now with 10% more bulk!

    Just noticed, the E2's name is still 3.1 instead of 3.2...
    I maek 3D mdoels adn paly veido gaems!

  7. #7
    Mario, hard at work Filipe's Avatar
    Join Date
    Jun 2007
    Location
    Portugal - Lisbon
    Posts
    401
    Blog Entries
    1

    Default Re: BulkOS 3 - now with 10% more bulk!

    Quote Originally Posted by Azrael View Post
    It would be nice if it was compiled, and there was a command to invoke the compiler at runtime on a specific string.
    That's what I've been thinking about, it's very possible, I'm just not sure yet how I'd accomplish it, and how I'd still keep the...wait, just figured that part out....There's still alot of things I'll have to iron out before even getting started on the actual code, but I think I might attempt to use an array, have the compiler push values and strings into the array, and then come up with a short-form code that would be created by the compiler, something like..

    Code:
    mov 1 this is a string yay.;
    would translate to:
    Code:
    m 1 1
    The second '1' being the string's index in the array...Off the top of my head I believe this would be much faster, since the current parser runs alot of checks on all the strings every single time, regardless of what the command is.

    Thoughts? Am I in the right path with this way of thinking?

    Quote Originally Posted by ShadowBrain View Post
    Just noticed, the E2's name is still 3.1 instead of 3.2...
    Oopsie, minor mistake, I often neglect the expression's name D:


    Edit:
    Made some progress on the compiler, won't go into details right now, but right now this:

    Code:
    prt Hello my name is #name
    Is turned into this:
    Code:
    p $3 $4 $5 $6 #7
    Numbers aren't transformed in any way. I think I'll attempt to compact those extra strings into a single one.

    Edit2:

    Strings now collapse correctly, this:

    Code:
    prt Hello, my name is #name and I like bacon!;
    Becomes this:

    Code:
    p|$1|#2|$3;
    Right from the start, I expect this'll cut ops by atleast half on most operations.

    Edit3:

    The first tests confirm what I mentioned previously. Operations per second increased to over 30 (couldn't get a precise reading yet), at only 300 op/s, compared to 6 operations at 1200op/s on the previous version.

    Edit4:

    The basics are laid down, the jmp structure now works MUCH better, I got the E2 up to 2300 op/s, at a speed AT LEAST 20x faster than before, and it was doing a pretty intensive operation.

    Yay!


    Edit5:
    Original bulkcode:
    Code:
    Main:;
    prt Hello;
    wait 1000;
    jmp Main;
    Compiled code:

    Code:
    Main:p|$1w|$2j|1
    Last edited by Filipe; 01-28-2010 at 05:50 PM.
    beep boop

  8. #8
    That furred thing Black Phoenix's Avatar
    Join Date
    Feb 2007
    Location
    Kyiv, Ukraine
    Posts
    3,565

    Default Re: BulkOS 3 - now with 10% more bulk!

    Shouldn't you like... compile into bytecode instead of strings? That'll cut down even more of your ops
    I'm a wire-crazy person with a tail.

    Take a daily journey into my brain

    D2K5

  9. #9
    Ursus maritimus Drunkie's Avatar
    Join Date
    Feb 2009
    Location
    Canada
    Posts
    5,662
    Blog Entries
    1

    Default Re: BulkOS 3 - now with 10% more bulk!

    This is awesome, good job.
    Love the similarities to assembly.

+ Reply to Thread

Similar Threads

  1. BulkOS > Oh gosh.
    By Filipe in forum Finished contraptions
    Replies: 16
    Last Post: 01-27-2010, 03:48 PM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
proceed-collector
proceed-collector
proceed-collector
proceed-collector
linguistic-parrots
linguistic-parrots
linguistic-parrots
linguistic-parrots