Programming and general geekiness.

Archive for July, 2011

If Windows 8 gets one thing right…

At the moment I am waiting for the Bing Bar uninstaller to initialize. After that I have a list of about 60 other programs to take off my computer – most are quite small, but with a few exceptions. I am doing this on a relatively average computer but I expect to be here for most of the day. The programs that I am getting rid of vary in type. Some are pointless little things I downloaded once to complete a task (I have about four unzipping programs for different file types), others are large applications that I have on other computers that run them better. The irritating ones, however, are ‘drivers’ and ‘support software’. When this computer was new it came with a very large program (4GB) with ‘support software’ for the system. The computer was made by a popular manufacturer. I have never used the software and I haven’t got a clue waht it does. Any problems I’ve had with the computer have either been solved by the 8 page problems booklet it came with or a quick Google search.

Furthermore, the router that I use came with about half a gigabyte of software detailing how to contact customer support. Again the router was made by a popular provider. I have never had any problems with it. Quite why it needs drivers when it is an ordinary Ethernet router I do not know. But ironically, it isn’t just this computer that acts like this. I have a computer with a graphics card made by a very popular manufacturer however the ‘driver’ for this is a giant complex application detailing loads of settings I’ve never needed or used. It is the same for many popular bits of hardware – they come with tonnes of rubbish.

Therefore Windows 8 really needs to change things. If there is a proper driver management system where all my drivers come from Windows Update and are lightweight, I’ll be happy. If there is a proper way of managing applications, I’ll be happy. I should be able to press one button to get rid of an application, but right now I have to wait for Windows Installer to catch up and do something. So I beg that if Windows 8 gets one thing right, it’ll be that everything is simple and easy in regard to the horror of uninstalling applications.

Here is my list of things I don’t like about uninstalling programs:

  • Having to be shown a survey after the installation has finished asking why I uninstalled (even more annoying if it has to open in IE)
  • Taking ages to load the uninstaller
  • Closing programs I am using which have nothing to do with the original program
  • Leaving programs on my computer that should have been uninstalled before hand
  • Leaving half the program on my computer claiming it is ‘preferences’ that I might like to use next time
  • Really bad estimates to how long it will take to uninstall
  • Scaring me out of the uninstaller (YOUR COMPUTER WILL NOT WORK IF YOU UNINSTALL THIS PROGRAM BECAUSE I’LL DELETE FILES FROM SYSTEM32! HA HA HA! kind of thing)
  • Progress bars that get to the very end and then restart again
  • Telling me that I can’t uninstall it because I’ve removed another component it requires – which requires it to uninstall
  • Full screen backgrounds with really disgusting gradients from the 90s.
  • Continually requesting admin permission
  • Making me restart
  • When it has finished, not taking me onto the ‘Finish’ screen automatically

ThomasScript source code

Because ThomasScript isn’t finished yet and I really am not worried about licensing it because it takes too much time (for my liking) I have decided to just put it here, on my blog. Because it doesn’t have a license I have decided to invent the following:

  1. If there are compiling errors, tell me
  2. If there are running errors, tell me
  3. If you computer (or anything else) is damaged because of the source code don’t tell me – it can be your fault for downloading it
That’s quite a simple version of GPL! Here is the code anyway:
import java.io.*;
import javax.swing.*;
import java.util.*;

class ThomasScript
{
	public String[] variables = new String[10000];
	public String[] values = new String[10000];
	public int next = 0;
	public Scanner in = new Scanner(System.in);
	
	public static void main(String[] args)
	{
		System.out.println("Welcome to ThomasScript");
		System.out.println("Recognized request from: " + args[0]);
		File source = new File(args[0]);
		if (source.exists())
		{
			System.out.println("Can confirm that the source exists");
			try
			{
				FileReader fr = new FileReader(args[0]);
				String code = "";
				BufferedReader buffer = new BufferedReader(fr);
				String line = "";
				String[] lines = new String[100000]; //CHANGE NUMBER TO NUMBER OF LINES IN FILE!!
				int nextone = 0;
				while ((line = buffer.readLine()) != null)
				{
					lines[nextone] = line;
					nextone++;
				}
				ThomasScript ts = new ThomasScript();
				ts.runCode(lines);
			}
			catch (IOException e)
			{
				System.out.println("Sorry, some sort of error occured.");
			}
		}
		else System.out.println("Sorry, file doesn't exist");
	}
	
	void runCode(String[] lines)
	{
		ThomasScript ts = new ThomasScript();
		System.out.println("Running code");
		System.out.println("-------------------------------------");
		System.out.println("");
		int max = 0;
		//Identifies the max number, temporary code only
		for (int a = 0; a < lines.length; a++)
		{
			if (lines[a] == null)
			{
				max = a;
				break;
			}
		}
		int a = 0;
		while (true)
		{
			if (lines[a] == null) break;
			String[] components = lines[a].trim().split(" ");
			String parts = "";
			for (int b = 1; b < components.length; b++) parts += components[b] + " ";
			if (components[0].equals("write"))
			{
				String[] args = getActualStringValues(parts);
				for (int b = 0; b < args.length; b++)
				{	
					if (args[b] == null) break;
					System.out.print(args[b]);
				}
				System.out.print("\n");
			}
			else if (components[0].equals("msg"))
			{
				String[] args = getActualStringValues(parts);
				String fullmessage = "";
				for (int b = 0; b < args.length; b++)
				{	
					if (args[b] == null) break;
					fullmessage += args[b];
				}
				JOptionPane.showMessageDialog(null, fullmessage);
				System.out.print("\n");
			}
			else if (components[0].equals("dim"))
			{
				for (int b = 1; b < components.length; b++)
				{
					variables[next] = components[b];
					values[next] = "";
					next++;
				}
			}
			else if (components[0].equals("set"))
			{
				String toGive = "";
				for (int b = 3; b < components.length; b++) toGive += components[b] + " ";
				toGive = toGive.trim();
				try
				{
					int index = 0;
					for (int b = 0; b < variables.length; b++)
					{
						if (variables[b] != null)
						{
							if (variables[b].equals(components[1]))
							{
								index = b;
								break;
							}
						}
					}
					if (components[2].equals("="))
					{
						String[] valueOut = getActualStringValues(toGive);
						if (valueOut[0] == null) valueOut[0] = toGive;
						values[index] = valueOut[0];
					}
					else if (components[2].equals("+"))
					{
						if (toGive.charAt(0) == '"')
						{
							String[] valueOut = getActualStringValues(toGive);
							values[index] += valueOut[0];
						}
						else if (toGive.charAt(0) == '$')
						{
							if (couldBeInt(getVariableValue(toGive)) && couldBeInt(getVariableValue(components[1])))
							{
								int result = (Integer.parseInt(getVariableValue(components[1])) + Integer.parseInt(getVariableValue(toGive)));
								values[index] = "" + result;
							}
							else
							{
								values[index] += getVariableValue(toGive);
							}
						}
						else if (couldBeInt(toGive))
						{
							int result = (Integer.parseInt(getVariableValue(components[1])) + Integer.parseInt(toGive));
							values[index] = "" + result;
						}
					}
					else if (components[2].equals("-"))
					{
						if (toGive.charAt(0) == '"')
						{
							String[] valueOut = getActualStringValues(toGive);
							values[index] += valueOut[0];
						}
						else if (toGive.charAt(0) == '$')
						{
							if (couldBeInt(getVariableValue(toGive)) && couldBeInt(getVariableValue(components[1])))
							{
								int result = (Integer.parseInt(getVariableValue(components[1])) - Integer.parseInt(getVariableValue(toGive)));
								values[index] = "" + result;
							}
							else
							{
								values[index] += getVariableValue(toGive);
							}
						}
						else if (couldBeInt(toGive))
						{
							int result = (Integer.parseInt(getVariableValue(components[1])) - Integer.parseInt(toGive));
							values[index] = "" + result;
						}
					}
					else if (components[2].equals("*"))
					{
						if (toGive.charAt(0) == '"')
						{
							String[] valueOut = getActualStringValues(toGive);
							values[index] += valueOut[0];
						}
						else if (toGive.charAt(0) == '$')
						{
							if (couldBeInt(getVariableValue(toGive)) && couldBeInt(getVariableValue(components[1])))
							{
								int result = (Integer.parseInt(getVariableValue(components[1])) * Integer.parseInt(getVariableValue(toGive)));
								values[index] = "" + result;
							}
							else
							{
								values[index] += getVariableValue(toGive);
							}
						}
						else if (couldBeInt(toGive))
						{
							int result = (Integer.parseInt(getVariableValue(components[1])) * Integer.parseInt(toGive));
							values[index] = "" + result;
						}
					}
					else if (components[2].equals("/"))
					{
						if (toGive.charAt(0) == '"')
						{
							String[] valueOut = getActualStringValues(toGive);
							values[index] += valueOut[0];
						}
						else if (toGive.charAt(0) == '$')
						{
							if (couldBeInt(getVariableValue(toGive)) && couldBeInt(getVariableValue(components[1])))
							{
								int result = (Integer.parseInt(getVariableValue(components[1])) / Integer.parseInt(getVariableValue(toGive)));
								values[index] = "" + result;
							}
							else
							{
								values[index] += getVariableValue(toGive);
							}
						}
						else if (couldBeInt(toGive))
						{
							int result = (Integer.parseInt(getVariableValue(components[1])) / Integer.parseInt(toGive));
							values[index] = "" + result;
						}
					}					
				}
				catch (Exception e)
				{
					System.out.println(e.toString());
				}
			}
			else if (components[0].equals("get"))
			{
				int index = -1;
				for (int i = 0; i < variables.length; i++)
				{
					if (variables[i].equals(components[1]))
					{
						index = i;
						break;
					}
				}
				if (index == -1) System.out.println("Variable not declared");
				else
				{
					String prompt = "";
					for (int i = 2; i < components.length; i++) prompt += components[i] + " ";
					String[] prompts = getActualStringValues(prompt);
					prompt = "";
					for (int i = 0; i < prompts.length; i++)
					{
						if (prompts[i] == null) break;
						prompt += prompts[i];
					}
					System.out.println(prompt);
					String input = in.nextLine();
					values[index] = input;
				}
			}
			else if (components[0].equals("getnum"))
			{
				int index = -1;
				for (int i = 0; i < variables.length; i++)
				{
					if (variables[i].equals(components[1]))
					{
						index = i;
						break;
					}
				}
				if (index == -1) System.out.println("Variable not declared");
				else
				{
					String prompt = "";
					for (int i = 2; i < components.length; i++) prompt += components[i] + " ";
					String[] prompts = getActualStringValues(prompt);
					prompt = "";
					for (int i = 0; i < prompts.length; i++)
					{
						if (prompts[i] == null) break;
						prompt += prompts[i];
					}
					System.out.println(prompt);
					int input = 0;
					input = in.nextInt();
					values[index] = "" + input;
				}
			}
			else if (components[0].equals("goto"))
			{
				if (couldBeInt(components[1]))
				{
					a = Integer.parseInt(components[1]) - 2;
				}
			}
			else if (components[0].equals("exit") || components[0].equals("quit")) break;
			else if (components[0].equals("if"))
			{
				String $var1 = getActualStringValues(components[1])[0];
				String $var2 = getActualStringValues(components[3])[0];
				int var1 = 0, var2 = 0;
				boolean var1true = false, var2true = false;
				if (couldBeInt($var1))
				{
					var1 = Integer.parseInt($var1);
					var1true = true;
				}
				if (couldBeInt($var2))
				{
					var2 = Integer.parseInt($var2);
					var2true = true;
				}
				
				if (components[2].equals("="))
				{
					if ($var1.equals($var2) && couldBeInt(components[4])) a = Integer.parseInt(components[4]) - 2;
				}
				else if (var1true && var2true)
				{
					if (components[2].equals(">"))
					{
						if (var1 > var2 && couldBeInt(components[4])) a = Integer.parseInt(components[4]) - 2;
					}
					else if (components[2].equals("<"))
					{
						if (var1 < var2 && couldBeInt(components[4])) a = Integer.parseInt(components[4]) - 2;
					}
					else if (components[2].equals(">="))
					{
						if (var1 >= var2 && couldBeInt(components[4])) a = Integer.parseInt(components[4]) - 2;
					}
					else if (components[2].equals("<="))
					{
						if (var1 <= var2 && couldBeInt(components[4])) a = Integer.parseInt(components[4]) - 2;
					}
					else if (components[2].equals("!="))
					{
						if (var1 != var2 && couldBeInt(components[4])) a = Integer.parseInt(components[4]) - 2;
					}
				}
				
			}
			else System.out.println("Unrecognized command on line " + (a+1));
			a++;
		}
		System.out.println("\n-------------------------------------\nRun complete");
	}
	
	String[] getActualStringValues(String parts)
	{
		parts = parts.trim();
		String[] returnOfTheString = new String[parts.length()];
		boolean inString = false;
		boolean inVariable = false;
		int position = -1;
		boolean started = false;
		for (int a = 0; a < parts.length(); a++)
		{
			char c = parts.charAt(a);
			if (c == '"' && !inString)
			{
				position++;
				inString = true;
			}
			else if (c == '"' && inString)
			{
				inString = false;
			}
			else if (inString)
			{
				if (returnOfTheString[position] == null) returnOfTheString[position] = "";
				returnOfTheString[position] += c;
			}
			else if (c == '$' && !inVariable)
			{
				position++;
				inVariable = true;
				returnOfTheString[position] = "$";
			}
			else if ((c == ' ' || a == parts.length()) && inVariable)
			{
				returnOfTheString[position] = getVariableValue(returnOfTheString[position]);
				inVariable = false;
			}
			else if (inVariable)
			{
				returnOfTheString[position] += c;
			}
			else
			{
				
			}
		}
		if (inVariable)
		{
			returnOfTheString[position] = getVariableValue(returnOfTheString[position]);
		}
		return returnOfTheString;
	}
	
	public String getVariableValue(String name)
	{
		int index = 0;
		for (int a = 0; a < variables.length; a++)
		{
			if (variables[a] != null)
			{
				if (variables[a].equals(name))
				{
					index = a;
					break;
				}
			}
		}
		return values[index];
	}
	
	boolean couldBeInt(String value)
	{
		value = value.trim();
		for (int a = 0; a < value.length(); a++)
		{
			char c = value.charAt(a);
			if (c != '0' && c != '1' && c != '2' && c != '3' && c != '4' && c != '5' && c != '6' && c != '7' && c != '8' && c != '9' && c != '.' && c != '-')
			{
				return false;
			}
		}
		return true;
	}
}

HTML5 Book

I have just added a new experiment to my site where you can view the site’s blog as a book. It has been produced using HTML5, CSS3 and a bit of jQuery. Click here to view it.

ThomasScript Bugs

I know that there are some bugs in ThomasScript. The language as a whole needs a lot of improvement, however the main bug at the moment is numbers. Theoretically when I write out something like ‘write “Hello, world. My favorite number is ” 10″ 10 should be interpreted as a number but the good old function that evaluates the strings has kindly decided that it won’t recognize numbers outside quote marks, so currently if statements regarding numbers require them to be in quotes:

NOT: if $number = 10 4

BUT if $number = “10″ 4

The current syntax for if statements at the moment is appalling because the number on the end (which can’t be in quote marks, strangely) redirects the interpreter to that line number. This means that ThomasScript can theoretically do branching, but it rubbish at it. Today I was asked the question what ThomasScript actually does, and I am yet to decide completely. I am currently thinking on developing it in someway so it can create interfaces. There might also be some sort of GUI instead of a very small Java console application – tested on Ubuntu 11.04 and Windows XP.

Of course, ThomasOS needs to run off of something…

ThomasScript v0.1 now available

ThomasScript is currently very bad, but the first executable is now available: http://code.google.com/p/thomasscript/

ThomasScript update

ThomasScript has know had all it’s basic commands finished except from branching…

ThomasScript will happen

Yesterday I finally got round to deciding that I would code ThomasScript. I had written some code about a month ago that roughly worked out how I could get started – but that was in C#, so today I have been porting it all over to Java. So far I have a relatively simple 150 line Java file that allows for ‘string evaluation’ and the write command. Here are the total commands:

Branching Commands:

  • if
  • else if
  • else
  • for
  • while

General commands:

  • write*
  • get
  • getnum
  • dim*
  • random
  • set

Variables:

  • PI – 3.141592
  • NEWLINE – \n
  • THEANSWERTOTHELIFEUNIVERSEANDEVERYTHING – 42
*Infinite arguments
I’ll probably add some more, but this is the basics of the language for now – it will be improved.

How to build a really simple programming language

This is not a tutorial. It is more a guide of how you could first approach things. It is assumed that you code in some object-orientated language. I think Java would be the best thing to get started with for this. I have based this on some code that I have already written as part of my ThomasScript project, which I intend to release at some point. Maybe.

First of all, I must assume that your programming language (and mine) and simple non-OO languages that have their code written out in text files, or somehow read text into some sort of String object to use as the basis of their ‘code’. Like you have a BASIC interpreter (which you would write) and a .BAS file that someone else would write and run. I’ll let you worry about how you get the content of the .BAS file.

Now that you have roughly figured this out, you need to think about how you are going to structure your language. Here is a rough example of mine:

dim $variable

set $variable = “Hello”

write $avariable

getnum $variable

set $variable + 1

write $variable

if ($variable > 10)

write “Big number”

else

write “Small number”

write “Going to run a function”

run someCode “Hello!”

code someCode $text

write $text

I think it is relatively clear how this program works and indeed how the programming language works – even though it is very simple. The first part of coding the language is to split everything into array, split into individual lines. You then take apart the first line by its spaces: dim and $variable. There is therefore a switch branch in your code that has all of these possible language keywords. The code for dim is found and the argument $variable is given to it. For simplicity purposes all variables start with a dollar symbol for easy lookup. The variable names are stored in a string array with a length of about 10,000 because it is unlikely that you’ll need more, or that you are using a language that allows for arrays of unlimited length. There is then another array with type of object (or equivalent) that stores the variable values. This is relatively simple.

Because it is relatively clear how all the other functions work from this, the next thing to look at is basic (very basic) logic. I have decided that to keep things simple at first I will only use >, <, ==, !=, <= and >=. I will not use any variation on AND or OR. The value in the brackets is now relatively easy to evaluate; you simply get the left hand value and compare using the appropriate operation to the right. After this you get all the code that is indented and run that.

This is a very basic article and doesn’t really discuss the full process, however it certainly offers a simple start. Please note I plan to write a simple version of ThomasScript to the syntax described above before releasing the source code (either C, C++ or Java).

The MacBook is dead, long live the MacBook Air

Apple is honestly the most incredible company in existence. The only thing that has really gone wrong for them in the last few years is Ping – everything else has been a success. And they’ve just done something to change it all again: the new Macs. The first major release was one that we already knew about: Mac OS X Lion. This is nothing new and I’ve certainly blogged loads about it. But we had some more surprises instead: a new Mac Mini, new MacBook Airs and a new ThunderBolt display (basically a slightly updated version of the old, but still stunning – if not expensive, Cinema Displays).

The new Mac Mini looks pretty similar to the old one, but this one is clearly going to be a big upgrade, and I wouldn’t blame anyone for buying one – they’re expensive but they are incredibly good, and fast. According to the Apple website the graphics and CPU are about twice as fast (but there is some complicated reasoning behind this, so for the majority of people this probably isn’t true). It appears to be smaller, but it looks great.

Then there is the new MacBook Air, again this looks very similar to the last, though there is not as great a speed improvement, it is more just Apple making sure all the Macs support ThunderBolt technology properly. Having said that, it is a MacBook Air with Lion, which is cool. But there is a very, very big change. This MacBook Air hasn’t just killed the old model; it appears to have killed the legendary MacBook. Those beautiful white (and black, I hear you cry) creations that were there to replace the ancient iBooks. Sadly, this is the end for the classic MacBook.

Jedi Jim

The Apprentice Final was fantastic last night (and I was really pleased that Tom won – well done), however there was one mistake:


JEDIS USE BLUE OR GREEN LIGHT-SABERS!

Follow

Get every new post delivered to your Inbox.