This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
theoriginalbit's profile picture

Creating A Bsod, Error Handling And Custom Errors

Started by theoriginalbit, 14 February 2013 - 05:02 PM
theoriginalbit #1
Posted 14 February 2013 - 06:02 PM
[left]Important![/left]

Now while this method of having a BSOD is good, it is NOT a replacement for testing your code. ALWAYS test your code. Also the method of implementing a BSOD is not perfect, there are some errors which will not appear in the BSOD, for example syntax errors will not since syntax is checked before running the program.


What normally causes a Blue Screen of Death (BSoD)

In Windows a BSoD happens when a system failure or error occurs, whether its caused by hardware, software, memory problems, etc. Normally when a BSoD occurs it is very helpful and tells you why it happened and sometimes how to fix it. Find more information on a BSOD here: http://en.wikipedia....Screen_of_Death

For Unix (thats you too Mac people) this BSoD is normally refered to as a 'kernal panic'. This kernal panic is normally caused by that same things as a BSoD, although it occurs less in Unix due to the fact that, well, Unix is awesome. Find more information on a kernal panic here: http://en.wikipedia....ki/Kernel_panic



Errors and You

Getting errors are a big part of debugging programs in any programming language. They quite often provide very useful information about what went wrong and how to fix it. An example of an error in ComputerCraft is
startup:4: attempt to call nil
this error tells us that we are trying to call a function that does not exist in the program 'startup' on line 4. Now these error messages can vary, but the basic format should always tell you the program, line number and the error message. Sometimes they can be bad, like this error
String expected
which comes up from time to time, off the top of my head I think its to do with the rednet api. Knowing how to read and interpret an error can make you a very powerful debugger and make fixing your programs very easy. However I am not here to tell you more about debugging and such, I am here to help you with error handling.


Error Handling (how the BSoD works)

Now in programming languages when an error occurs it needs to be handled. Now just a bit of a deviation… When a program is executing there is a data type, known as a stack, that contains where the program is up to, each time you call a function it is pushed on the top of the stack, and when the function finishes it is pushed off the stack and the previous stack item continues from where it left off. Now back to topic… When an error is raised it will continue down the stack until something handles it. If you don not handle the error in your code it will go back to whatever has called your program, if that program does not handle the error it will continue does that programs stack until it is handled. In the case of ComputerCraft the shell handles our errors and prints them to the screen.

Now as stated we can handle the errors ourself, just like we can create errors intentionally. Now in most high level programming languages to handle an error we can use a try/catch statement. For example in Java we would use this syntax:

try
{
  // what we want to do that can throw an error
}
catch(SomePreciseException e)
{
  // print out what we want for this specific exception
}
catch(Exception e)
{
  // generically catch any other errors that we did not expect or such
}

Now sadly in Lua we do not have a try catch statement. However in Lua we have a function called pcall, which means protected call. Now pcall can only run functions, so this means that we must surround our code that could cause errors in a function.

Now what pcall does is it calls its first argument, which is the function, in protected mode so that it catches any errors while it is running. If there are no errors pcall will return a true, plus any values that are returned by the call, otherwise it will return false and the error message. Now the error message does not need to be a string, infact it could be anything, including a table, but I shall leave those bits up to you to figure out completely.

So really for all intensive purposes using the error function is a throw and the pcall is a catch.


Making Errors

In Lua, just like other languages, we can also create errors. The most common method is by using the 'error' function but we can also use the assert function. Now say we have the following example;

local number = tonumber(read())
if not number then error("invalid input, not a number") end
print(number)
now while this is a completely valid example it can be simplified with assert like so

local number = assert(tonumber(read()), "invalid input, not a number")
print(number)
So assert will attempt the first parameter and if it returns false or nil then it will raise an error with the message in the second parameter.

Now as detailed previously when an error occurs there is location information that comes with it, it includes the file and line number that the error occurs. This is the same for assert as it raises an error. Sometimes however we don not wish the error to show as ours, for example, what if we are creating an api that needs to be called with a specific parameter. This is when we use the second parameter of the error function. This second parameter is the levelthat the error should be reported, that way we can blame someone else not us. So with this example

function this(str)
  if type(str) ~= "string" then error("Expected string, got "..type(str)) end
end
and this example

function this(str)
  assert(type(str) ~= "string", "Expected string, got "..type(str))
end
these would both point the finger at us, saying that our function is the one to have caused an error. Now unfortunately the assert function does not allow the use of the level argument. So if we wish to use the level we must do it with the error function like so

function this(str)
  if type(str) ~= "string" then error("Expected string, got "..type(str), 2) end
end
This will now point the finger at the function that calls ours. Now that we all know this, onto the BSoD

EDIT: After reading some of the code made by the CC devs, I have discovered that if you do a level of 0 on the error function it will not print the error message with the file name and line number. It is essentially

printError( 'Some Error' )
error()

this is a very handy trick to quickly exit the program, print a red message, but now show it as an error in the code. as such I have updated the assert function in the next section to also do the same.


A Custom Assert

Firstly I would just like to say thank you to user: Stary2001 on the #computercraft IRC channel for helping me with this code, wasn't in the right mind of thinking and he helped me.

Now as stated above unlike error assert does not have a level. Now this is essentially how the assert works

if not [someCondition] then
  error("Some message", 1)
end
Now while this is all well and good, as you can see it provides the default level 1, pointing the blame for the error to our function. Now as stated above, we can just use error(<msg>, 2) but consider this scenario:

local function someFunc( p1, p2, p3, p4, p5, p6, p7, p8 )
  if type(p1) ~= "string" then error("Arg1 expected string",2) end
  if type(p2) ~= "string" and type(p2) ~= "nil" then error("Arg2 expected string or nil",2) end
  if type(p3) ~= "boolean" then error("Arg3 expected boolean",2) end
  if type(p4) ~= "table" then error("Arg4 expected table",2) end
  if type(p5) == "number" then error("Arg5 numbers not number",2) end
  if type(p6) ~= "boolean" then error("Arg6 expected boolean",2) end
  if type(p7) == "nil" then error("Arg7 nil not allowed",2) end
  if not p8 then error("Arg8 nil not allowed",2) end
end
now thats a lot of code there that is not overly unreadable and if you're anything like me, you may have missed one or 2 end to the if statements as well, just to check the parameters

Now this is where a custom assert can come in handy. Here is a version of assert that has, optional, levels:

local function assert( condition, message, level )
  level = tonumber( level ) or 1
  level = level == 0 and 0 or (level + 1)
  if not condition then
	error( message or "assertion failed!", level )
  end
  return condition
end
Now if you don't provide a level, it will default to pointing finger at your code causing the error, just like the default assert, however now we can provide a level to the assert. so the example we used before now becomes this

local function someFunc( p1, p2, p3, p4, p5, p6, p7, p8 )
  assert( type(p1) == "string", "Arg1 expected string", 2 )
  assert( type(p2) == "string" or type(p2) == "nil", "Arg2 expected string or nil", 2 )
  assert( type(p3) == "boolean", "Arg3 expected boolean", 2 )
  assert( type(p4) == "table", "Arg4 expected table", 2 )
  assert( type(p5) ~= "number", "Arg5 numbers not allowed", 2 )
  assert( type(p6) == "boolean", "Arg6 expected boolean", 2 )
  assert( type(p7) ~= "nil", "Arg7 nil not allowed", 2 )
  assert( p8, "Arg8 nil not allowed", 2 )
end
Now while this isn't any shorter in lines, it is easier to read, and there is no worry about forgetting an end ;)/>


The Code

This is the basics behind the code

local function main()
  -- main code body goes here

  return true -- this is needed so that when the program ends normally the BSOD will not appear
end

local ok, err = pcall(main)

if not ok then
  -- an error has occurred so print the BSOD here
end

Now you don not need to have all your code inside the 'main' function, you can have functions outside if it, because as stated before the error will go until something handles it, which is our pcall on 'main'. So this code would work as well

local function doSomething()
  error("Some bad error! :P/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>",2)
end

local function main()
  doSomething()

  return true -- this is needed so that when the program ends normally the BSOD will not appear
end

local ok, err = pcall(main)

if not ok then
  print(err)
end

Now there are ways for us to print our own errors and exit so the BSOD does not appear

local running = false

local function main()
  if not running then
	print("You silly person!")
	return true
  end

  return true
end

local ok, err = pcall(main)

if not ok then
  print(err)
end
By using return true we can stop the bsod from showing up, while still exiting the program and telling the person the error message that is not bad enough to require a BSOD.

We can also pass parameters to functions with pcall, there will be an example in the next code snippet.
Lets say that we have areas in code that we want to thown an error and handle it in our own code, lets say an invalid file or something, we can do this

local function openFile(path)
  local handle = assert(io.open(path, "r"), "File does not exist! :(/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>") -- now if there is a problem with this it will throw an error
  handle.close()
end

local function main()
  write("Please input a file: ")
  local input = read()
  local ok, err = pcall(openFile, input)
  if not ok then
	print(err)
  else
	print("That file exists! :)/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>")
  end
end

local ok, err = pcall(main)
if not ok then
  print(err)
end
Now in the above example we are handling the potential error in the code meaning that it does not go back to the BSOD, but instead to our pcall in the code.

When programming now, with the BSOD, I like to use a C-style main function like so

local function main(argc, argv)

  return true
end

local ok, err = pcall(main, #{...}, {...})
if not ok then
  print(err)
end
This code passes the runtime argument count and arguments to the main function. Very C-style programming hey ;)/> We can then validate the runtime arguments inside the main, obviously its just as easy to do this outside the main, but either way, does not make a huge difference.

Now this is an example that I made and send to someone else, read the comments for some information

-- functions can be out here, thats fine
local function someFunction()
  error("Input error")
end

-- this is a very C-style language feel to program entry
local function main(argc, argv)
  -- main program body goes in here
  -- you can do argument checking in here, or before the pcall if you wish
  -- either way, but there is support for it here, argc is the count, argv is the arguments

  -- functions can also be in our main function
  local function anotherFunction()
		error("Bad runtime error!")
  end

  -- you can even handle errors yourself if you do not want a certain error to go to the bsod
  local ok, err = pcall(someFunction)
  if not ok then
		print("We got an error from someFunction and 'caught' it here, it gave us "..err)
  end

  if math.random(1,4) == 4 then
		anotherFunction()
  end

  return true -- absolutely needed or else if will show BSOD when quitting without error!
end

local ok, err = pcall(main, #({...}), {...}) -- pass the argument count and the arguments to main

if not ok then
  -- errors, except syntax errors, if not caught in the main program body will come here.
  -- Errors when they occur will go down the stack returning each function until something handles it,
  -- normally this would go to the shell, but since we are using pcall we are catching this error and
  -- then printing it here

  -- draw the BSOD here however you wish
  print("BSOD: Really bad runtime error "..err)
end


A full working example, BSOD and all!

Now I'm not going to go into detail about how this works here, have a read through and see if you can understand it, and if not comment on this thread and ask
Spoiler

local isDev = true  -- set this for your own development environments, it will make the BSOD print a line number.

local function main(argc, argv)
  if argc ~= 0 then
	if argc == 1 then
	  if argv[1] == "-help" then
		print("Valid arguments -help -test")
		return true -- we want to exit but not trigger the BSOD for something this trivial
	  elseif argv[1] == "-test" then
		print("Tested, now running")
	  else
		print("Invalid argument, "..argv[1].." run with -help to see valid arguments")
		return true -- we want to exit but not trigger the BSOD for something this trivial
	  end
	else
	  print("This program only supports 1 argument not "..argc)
	  return true -- we want to exit but not trigger the BSOD for something this trivial
	end
  end

  -- function calls and main code body here

  return true
end

local ok, err = pcall(main, #({...}), {...})

if not ok then
  -- for the following 2 functions are from my Extended String Library...
  local split = function(str, pat) local t = {} local fpat = "(.-)"..pat local last_end = 1local s, e, cap = str:find(fpat, 1) while s do if s ~= 1 or cap ~= "" then table.insert(t,cap) end last_end = e + 1 s, e, cap = str:find(fpat, last_end) end if last_end <= #str then cap = str:sub(last_end) table.insert(t, cap) end return t end
  local trim = function(str) return (str:gsub("^%s*(.-)%s*$", "%1")) end

  -- localize these as they are only used here
  local setColors = function(bg, txt) if not (term.isColor and term.isColor()) then return false end if txt then term.setTextColor(txt) end if bg then term.setBackgroundColor(bg) end end
  local clear = function(col) if col then term.setBackgroundColor(col) end term.clear() end
  local cwrite = function(msg, y, offset) local sw,sh = term.getSize() term.setCursorPos(sw/2-#msg/2, (y or (sh/2)) + (offset or 0)) write(msg) end
  local errHeader = function(text, y, centre) setColors(colors.white, colors.blue) if centre then cwrite(text, y) else term.setCursorPos(1,y) print(text) end setColors(colors.blue, colors.white) end
  local printMsg = function(text, y) term.setCursorPos(1,y) print(text) end
  local waitForKey = function() while true do local e,k=os.pullEventRaw("key") if k == 28 or k == 156 then break end end end
  local err = split(err,":")
  local sw,sh = term.getSize()

  clear(colors.blue)

  -- the error headers
  errHeader(" ERROR : "..( err[#err-2] and string.upper(err[#err-2]) or "<UNKNOWN>").." ", 2, true)
  errHeader(" Error Description ", 7, false)
  errHeader(" Reporting the Issue ", sh-7, false)

  -- BSOD content
  printMsg("An error has occurred during runtime with \'"..(err[#err-2] or "<unknown>").."\' and the program has ceased working.", 4)
  printMsg(trim((isDev and "Line "..(err[#err-1] and err[#err-1] or "<unknown>")..":" or "")..err[#err]) or "<No error message supplied>",9)
  printMsg("If this problem persists please try updating the program with '-update' and if the problem still persists report the issue with '-report'",sh-5)

  cwrite("Press enter to quit...",sh-1)
  waitForKey()

  term.clear(colors.black)
  term.setCursorPos(1,1)
end

I hope this tutorial was helpful in learning about error handling and controlled error creation, oh and a making a BSOD. Please feel free to leave any suggestions or comments :)/>
Edited on 06 July 2014 - 02:23 AM
Dlcruz129 #2
Posted 14 February 2013 - 06:21 PM
Nice! I think I'll add this to my operating system.
theoriginalbit #3
Posted 14 February 2013 - 06:28 PM
Nice! I think I'll add this to my operating system.
:)/> I'm glad you found it useful :)/>
superaxander #4
Posted 14 February 2013 - 07:39 PM
That's gonna help me so much. Thanks now I know how assert works and pcall. In some of my old program's in lua I tried using try but it didn't work. Now here is the solution thanks. I'm so happy now!
theoriginalbit #5
Posted 14 February 2013 - 08:23 PM
That's gonna help me so much. Thanks now I know how assert works and pcall. In some of my old program's in lua I tried using try but it didn't work. Now here is the solution thanks. I'm so happy now!
No problems :)/> thank you for the feedback :)/> I look forward to seeing your new programs :)/>
NDFJay #6
Posted 15 February 2013 - 12:36 AM
Got to say, this is one sexy tutorial :)/> Made my error handling function now :)/> if an error is caught it does this >>

Spoiler

EDIT–

When Click on either "Email Error to NDFJay" or "Save Error Log" this happens >>
SpoilerSave Error Log:


Viewing the Error Log:


Emailing me the error log:


and finally me viewing the email:

:D/>
Edited on 15 February 2013 - 12:14 AM
theoriginalbit #7
Posted 15 February 2013 - 12:39 AM
Got to say, this is one sexy tutorial :)/> Made my error handling function now :)/> if an error is caught it emails me haha
Why thank you :)/> Lol nice. gotta make sure that you minimise on the bugs then ;)/> you don't wanna be spammed with emails :P/>

EDIT: I LOVE the BSOD, well it looks a little like a Kernal Panic, but in any case, love it :D/>
Edited on 14 February 2013 - 11:52 PM
NDFJay #8
Posted 15 February 2013 - 12:45 AM
Got to say, this is one sexy tutorial :)/> Made my error handling function now :)/> if an error is caught it emails me haha
Why thank you :)/> Lol nice. gotta make sure that you minimise on the bugs then ;)/> you don't wanna be spammed with emails :P/>

Thats my next job haha, so far the only error I get is that one that I forced by creating a false variable haha
theoriginalbit #9
Posted 15 February 2013 - 12:50 AM
Thats my next job haha, so far the only error I get is that one that I forced by creating a false variable haha
I figured as much :)/> ;)/>
SuicidalSTDz #10
Posted 15 February 2013 - 01:07 AM
NDF-Jay is right, this is one "sexy" turtortial. I can see some places where this could benefit users with EnderOS. Nice work :)/>
theoriginalbit #11
Posted 15 February 2013 - 01:19 AM
NDF-Jay is right, this is one "sexy" turtortial. I can see some places where this could benefit users with EnderOS. Nice work :)/>
Why thank you :)/> I actually have been using this in the development of cctube for quite some time and when I got some time today away from cctube development I decided to type it up and post it for others to benefit from :)/> glad you're all liking it :)/>
NeverCast #12
Posted 15 February 2013 - 08:46 AM
Awesome tutorial TheOriginalBit :D/>
Very nice!

Also regarding Kernel Panics less often in Unix, That could be perceptive as typically smart people use Unix and are less likely to break it. Another probably reason is that the Unix Kernel is modular, unlike Windows where it's core components are loaded at boot and that's it. You can load DLL libraries, but they are in the user space, and loading drivers in to Windows often requires a restart for the reason that it's loaded during boot.

The difference here is that if for example, you have an incorrect sound or graphics driver, and your device sends an unknown command to that said driver, it could cause the driver to error. This cascades to the rest of Windows as it's one giant machine. Causing the BSOD.

In Unix, the drivers are loaded as modules ( Unless compiled in to the kernel as some default ones may be ). If a module is to crash, it will not typically take down the Kernel. Unix will just unload that driver and spill some grumbling rant in to your error logs.
This doesn't make Unix immune, and it does make drivers are little bit slower in Unix if they're not compiled in to the kernel, because they must communicate with messages and syscalls.

I hope this information is correct, this is based from my understanding of the how the two systems work and I cannot cite this information. Feel free to critique this information if you can be certain something is invalid (:

Edit: Also, it's 'Popped' off the stack :P/>
AnthonyD98™ #13
Posted 15 February 2013 - 09:11 AM
This could be useful for SelectOS especially in debugging!
theoriginalbit #14
Posted 15 February 2013 - 09:37 AM
Awesome tutorial TheOriginalBit :D/>
Very nice!

-big snip-
Thanx :)/>
If what you and I understand is correct, thats exactly my point. Unix is awesome. :P/>

This could be useful for SelectOS especially in debugging!
:)/> glad it helped :)/>
LBPHacker #15
Posted 16 February 2013 - 06:41 AM
Nice! I think I'll add this to my operating system.

Heh :D/> Same here. (Everybody's writing an own OS huh?)
theoriginalbit #16
Posted 16 February 2013 - 01:18 PM
Heh :D/> Same here. (Everybody's writing an own OS huh?)
:D/>

Yeh door locks and OSes are the most common programs
Dlcruz129 #17
Posted 16 February 2013 - 04:15 PM
Heh :D/>/> Same here. (Everybody's writing an own OS huh?)
:D/>/>

Yeh door locks and OSes are the most common programs

I'm not gonna release mine. You're welcome. :P/>
theoriginalbit #18
Posted 16 February 2013 - 04:21 PM
I'm not gonna release mine. You're welcome. :P/>
I'm not saying don't release it, I'm saying they are just the most common.
Shnupbups #19
Posted 16 February 2013 - 04:32 PM
Awesome! Will put this in my custom shell (not OS) that I may or may not release.
theoriginalbit #20
Posted 16 February 2013 - 04:35 PM
Awesome! Will put this in my custom shell (not OS) that I may or may not release.
lol. thanx
Dlcruz129 #21
Posted 16 February 2013 - 04:37 PM
I'm not gonna release mine. You're welcome. :P/>/>
I'm not saying don't release it, I'm saying they are just the most common.

I wasn't planning on releasing it in the first place.
theoriginalbit #22
Posted 16 February 2013 - 04:42 PM
I wasn't planning on releasing it in the first place.
Lol ok then :P/>
GravityScore #23
Posted 17 February 2013 - 10:58 PM
Great tutorial. I always thought BSoD were something that was very low-level in the system, and if they were in CC you could only call it a BSoD if it were in the BIOS or somewhere close to that. TIL Firewolf has a BSoD (except it's red, so a RSoD)
theoriginalbit #24
Posted 17 February 2013 - 11:02 PM
Great tutorial. I always thought BSoD were something that was very low-level in the system, and if they were in CC you could only call it a BSoD if it were in the BIOS or somewhere close to that. TIL Firewolf has a BSoD (except it's red, so a RSoD)
Thanx :)/>
BSoD/Kernal Panic is normally very low-level in the system, as it caused by something low-level going wrong. However in a standard CC program this is as low-level as we can get, so thats as low as we go ;)/> :P/>

Haha, how did you not know your own program had a RSoD? :P/> haha RSoD, kinda just makes me think RRoD :P/>
theoriginalbit #25
Posted 19 February 2013 - 08:32 PM
Added new section "A Custom Assert" to OP
theoriginalbit #26
Posted 21 February 2013 - 08:08 PM
Bug fix in code for "A custom assert"
superaxander #27
Posted 21 February 2013 - 08:10 PM
I don't understand how the custom assert works?
theoriginalbit #28
Posted 21 February 2013 - 08:18 PM
I don't understand how the custom assert works?
It works just like the assert that is default to Lua…… if you don't understand my explanation lets see if I can find a tutorial on it…… here is one

Ok so what the custom assert does is adds a level to the error. now what a level does.

Assume we have this code:

function three()
  assert( false, "An error", <level>)
end

function two()
  three()
end

function one()
  two()
end

one()
Now if we don't specify a level the line number (and program name) will be pointing to where the error occurs, in this case line 2. If we supply a level of 2, then it will point to 2 levels down the program stack, which is the function calling our function, which would be line 6. If we give a level of 3 it will show the error being at line 10 (being the function that is 3 levels down from the top of the stack). now if we supplied a level of 5, then well that is before our function isn't it, so the error then gets pointed to the shell, if we do 6 it will be bios, anything above the very bottom level (bios) will give unexpected results.
superaxander #29
Posted 21 February 2013 - 08:28 PM
Now I understand thanks
theoriginalbit #30
Posted 21 February 2013 - 08:29 PM
Now I understand thanks
No problems :)/>
remiX #31
Posted 23 February 2013 - 06:52 AM
Hmm Bit, the split function in your test code in the OP is missing one important thing … the letter 't' …

Right now it just returns, but it needs to be return t :P/>
theoriginalbit #32
Posted 23 February 2013 - 01:33 PM
Hmm Bit, the split function in your test code in the OP is missing one important thing … the letter 't' …

Right now it just returns, but it needs to be return t :P/>
Hmmm, I wonder how that got removed. It was literally a copy/paste of a functioning bsod.
remiX #33
Posted 24 February 2013 - 12:23 PM
Hmm Bit, the split function in your test code in the OP is missing one important thing … the letter 't' …

Right now it just returns, but it needs to be return t :P/>
Hmmm, I wonder how that got removed. It was literally a copy/paste of a functioning bsod.

Scumbag copy pasta :P/>
momona5 #34
Posted 20 March 2013 - 12:19 PM
Got to say, this is one sexy tutorial :)/> Made my error handling function now :)/> if an error is caught it does this >>

Spoiler

EDIT–

When Click on either "Email Error to NDFJay" or "Save Error Log" this happens >>
SpoilerSave Error Log:


Viewing the Error Log:


Emailing me the error log:


and finally me viewing the email:

:D/>


Do you have the code for this? I'm loving the look of it.If you do still have it could I use it?
NDFJay #35
Posted 21 March 2013 - 03:00 AM
–snip

Do you have the code for this? I'm loving the look of it.If you do still have it could I use it?

I made it into an API which can be found HERE with all its explanations and how to use it, the API allows custom crash screens with custom text/colours and allignment as well as saving the crash log to a custom location of your choice and works with CC 1.3 and up
PixelToast #36
Posted 21 March 2013 - 04:46 AM
meh, id rather just not make errors in my code
theoriginalbit #37
Posted 21 March 2013 - 04:51 AM
meh, id rather just not make errors in my code
so you never use the assert or error functions in any of your programs?
PixelToast #38
Posted 21 March 2013 - 05:06 AM
some of them
but i dont know why you would want to
i would prefer a UI to do that
theoriginalbit #39
Posted 21 March 2013 - 05:09 AM
A UI to do assert? O.o
Assert is one of the best tools that can be used in any language.
theoriginalbit #40
Posted 02 April 2013 - 06:32 AM
After reading some of the code made by the CC devs, I have discovered that if you do a level of 0 on the error function it will not print the error message with the file name and line number. It is essentially

printError( 'Some Error' )
error()

this is a very handy trick to quickly exit the program, print a red message, but now show it as an error in the code. as such I have updated the assert function in the 'A Custom Assert' section to also do the same.
theoriginalbit #41
Posted 18 April 2013 - 02:16 AM
+ Added the tutorial by myself and remiX on 'How To Use ccSensors' to OP so that I can have all my tutorials in one place.
Lyqyd #42
Posted 18 April 2013 - 04:19 AM
What on earth for? Tutorials should each have their own topics.
superaxander #43
Posted 18 April 2013 - 04:20 AM
What on earth for? Tutorials should each have their own topics.
Why shouldn't thay they be in the same topic?

EDIT: they instead of thay -_-/>
Lyqyd #44
Posted 18 April 2013 - 04:28 AM
When they have their own topics, it is easier to find tutorials by title when browsing the section, it is easier to search for them (as the title can hold useful information ("xyz's tutorials" is a useless title), and when you leave a tutorial in the topic where it started, you don't throw away all of the existing conversation on it. Essentially, they're harder to find, and they're less useful when you do find them. Imagine if the entire tutorials section was just "xyz's tutorials", from top to bottom, for everyone that wrote a tutorial. A new user would just have to guess what might be in each one, and that's frustrating and silly. Centralizing things for the sake of a signature link is very backwards thinking.

I'm not going to merge the topics or even lock the other one. Merging them squishes the topics together and interlaces the posts by date, so the topic would be confusing, and locking it prevents him from moving the tutorial back (which I suggest).
superaxander #45
Posted 18 April 2013 - 04:29 AM
When they have their own topics, it is easier to find tutorials by title when browsing the section, it is easier to search for them (as the title can hold useful information ("xyz's tutorials" is a useless title), and when you leave a tutorial in the topic where it started, you don't throw away all of the existing conversation on it. Essentially, they're harder to find, and they're less useful when you do find them. Imagine if the entire tutorials section was just "xyz's tutorials", from top to bottom, for everyone that wrote a tutorial. A new user would just have to guess what might be in each one, and that's frustrating and silly. Centralizing things for the sake of a signature link is very backwards thinking.

I'm not going to merge the topics or even lock the other one. Merging them squishes the topics together and interlaces the posts by date, so the topic would be confusing, and locking it prevents him from moving the tutorial back (which I suggest).
Good point didn't think of that. I guess we'll have to wait what TOBIT says…
Sariaz #46
Posted 18 April 2013 - 06:55 PM
Very good tutorials. Btw do you know if they fixed the bugs with the proximity detector because in the version I used the proximity detecters were extremely buggy. Sometimes they could find there targets some times they couldn't, other times they found the target but gave inconsistent data, or most aggravatingly they would randomly fix when i hadn't even touched the code making it more confusing.
Spongy141 #47
Posted 19 April 2013 - 03:57 AM
Nice.
theoriginalbit #48
Posted 30 April 2013 - 09:32 PM
reverted the OP back to just be a stand alone thread.
Zoinky #49
Posted 01 May 2013 - 01:10 AM
Very nice tutorial! Good work :D/>
Cranium #50
Posted 14 May 2013 - 06:17 PM
I recommend using anchors for your list here. Helps to have a table of contents if you plan on expanding this. use
[anchor='<anchorName>']
to create an anchor, and link to that position in the page by using "topic_url/#<anchorName>". It definitely helps for long topics.
Shnupbups #51
Posted 14 May 2013 - 06:19 PM
Where's the topic for your other tutorial? I hadn't had time to read it.
theoriginalbit #52
Posted 14 May 2013 - 09:39 PM
I recommend using anchors for your list here. Helps to have a table of contents if you plan on expanding this. use
[anchor='<anchorName>']
to create an anchor, and link to that position in the page by using "topic_url/#<anchorName>". It definitely helps for long topics.
Thanks, I always have intentions to do it, never get around to it…

Where's the topic for your other tutorial? I hadn't had time to read it.
here they are: Binary and Computer Logics | How to Use ccSensors
Zudo #53
Posted 23 May 2013 - 12:12 PM
Hi, for your BSoD, will it appear when a program crashes? I am making a custom shell
theoriginalbit #54
Posted 23 May 2013 - 12:25 PM
Hi, for your BSoD, will it appear when a program crashes? I am making a custom shell
Well to put it in the context of my examples and your program, the BSoD would only show if the shell itself errors, not the programs that it runs. But the idea is still the same and can be applied to programs that the shell runs.
Cain #55
Posted 02 June 2013 - 05:35 PM
Very useful, thank you. I will use this later.
Zudo #56
Posted 19 June 2013 - 12:37 PM
Using this!
FNCPro #57
Posted 23 June 2013 - 03:11 PM
Time to update my OS with this :D/>
Thanks!
hbomb79 #58
Posted 26 July 2014 - 06:10 AM
When you said the function can be outside of the main function, does that work for programs, lets say i use shell.run or something, but i run it from a function that was called by the main function so;


function runProg()
  shell.run"SomeProgram"
end
function main()
  runProg()
end

local ok, err = pcall(main)
if not ok then
  print(err)
end


Would it still catch an error that occurred in the "someProgram" program?
theoriginalbit #59
Posted 26 July 2014 - 06:56 AM
Would it still catch an error that occurred in the "someProgram" program?
Unfortunately it won't due to how shell.run works. shell.run calls os.run which uses pcall internally. it will return false when the program has failed to run or errored while running, but it will also print said error.
hbomb79 #60
Posted 26 July 2014 - 07:03 AM
So the best way is to have the BSoD as an API and the catching statements in all scripts?
theoriginalbit #61
Posted 26 July 2014 - 07:28 AM
or if it is more of an OS style system, you could override os.run to not have the pcall functionality, so your main pcall catches it instead.
hbomb79 #62
Posted 26 July 2014 - 08:12 AM
Hmm, Maybe thats a better idea
Alice #63
Posted 02 August 2014 - 06:45 AM
Looks like a great tutorial. +1 to this. I might use this if/when I get back into ComputerCraft and finally make either BiOS or PotatOS
theoriginalbit #64
Posted 02 August 2014 - 08:51 AM
I'm glad it helped.
Britminecraty #65
Posted 15 December 2014 - 05:21 PM
Tested it after ages of coding, And I got this error message:
bios:206: [string "error"]:20: cannot use '…'
outside a vararg function

WAT DOES IT MEAN?
KingofGamesYami #66
Posted 15 December 2014 - 06:18 PM
Tested it after ages of coding, And I got this error message:
bios:206: [string "error"]:20: cannot use '…'
outside a vararg function

WAT DOES IT MEAN?

Without your code, I'd say you mistyped a concat (..) with … (which does something totally different)
Britminecraty #67
Posted 15 December 2014 - 08:22 PM
Tested it after ages of coding, And I got this error message:
bios:206: [string "error"]:20: cannot use '…'
outside a vararg function

WAT DOES IT MEAN?

Without your code, I'd say you mistyped a concat (..) with … (which does something totally different)
Thanks man. I'll look through my code now and look for any other syntax errors while i do that.