Teiwaz
Teiwaz is a programming language designed by PSTF. In the timeline 284436, it was designed by Wolfgang Thinönosk in Scandinavia Union as variant of Python which was created by Guido von Rossum of Netherlands in the timeline 1.
The document is also in the timeline 284436, which was written by Jake Douglas. And the document was transmitted to the timeline 1, and got revised by PSTF.
Intro
Teiwaz is almost like Python in our timeline, it is strong and easy.
Of course, the logo of Teiwaz is based on the Rune ᛏ, which transliterates as "T".
Basic Syntax
Our First Program
#hello.twz write("Hello, Teiwaz!")
All Teiwaz programs must have the file extension .twz
. If you do not indicate the file name with a comment at the beginning of the program, you must specify the name when saving.
In timeline 284436, the most common operating system is BlockOS from UniverseLight company at the U(S)SA. It is quite like Windows, so we will use the BlockOS instead of Windows from our timeline to make example.
In this program, the output should be this:
Hello, Teiwaz!
If you can't get this output, you may met these condition:
- Severe Error. At this time Teiwaz console will write an exceptionresume.
- Things in the quotation mark is wrong, such as you accidentally wrote it into "Hello, world!" or something else.
You will solve this problem with these methods:
- Read the exceptionresume carefully, it might provide you with clues.
- Stop and take a break for a while, then deal with it later.
- See how others have written it. Maybe you missed some steps that he/she happened to include.
Variables, Constants, and Simple Data Types
We already written hello.twz, but what happened when the Teiwaz interpreter was running it?
It tries to interpret the program. Such as, when it meet "write" then it prints things in the parentheses after the function.
When we're programming, some editor may having a syntax highlight. That's helpful for you when you're just touching Teiwaz.
Alright, let's say about datas.
Variables
Open the hello.twz again, then change the program into this:
#hello.twz message <- "Hello, Teiwaz!" write(message)
In this program, we added a variable that points to a specific string: message. Every variable should point to a value.
Open the hello.twz for the third time, then extend the program.
#hello.twz message <- "Hello, Teiwaz!" write(message) message <- 1145141919810 write(message)
Hello, Teiwaz! 1145141919810
As you can see, variables can change its value every time.
Note that Teiwaz is a weakly typed language, so you can freely assign a value of a different type to a variable.
The naming rule of variables are same in Python, but with these cautions:
- You should not use all uppercase letters as variable names now. Although it can still be used, we have given it a new meaning — constant.
- Be cautious when using the lowercase letter 'l' and the uppercase letter 'O'. They are likely to be mistaken for the numbers 1 and 0 (at least in some fonts).
- Although you can use a function name as a variable name, it's best not to do so.
- Try to make your variable names understandable but also concise.
NameError
We are now going to intentionally introduce some errors into our code. Open the hello.twz, then change the code to this:
#hello.twz message <- "Hello, Teiwaz!" write(messsge)
Of course, we didn't defined messsge before, so Teiwaz doesn't know what it to do, then throw an ExceptionResume:
Program failed to run. ExceptionResume(first one is oldest one): | Error occured in "hello.twz", at line 3, in __main__: | write(messsge) | ~~~~~~~ NameError: Can I eat "messsge"?
In the third line of the program, we deliberately misspelled 'message' as 'messsge'. In exceptionresume, Teiwaz points out where there is an error in the code and highlights the erroneous code with a wavy line. Of course, Teiwaz doesn't care whether your variable is misspelled, but it requires you to use a label that has already been defined. What would happen if we also wrote 'message' as 'messsge' in the second line?
#hello.twz messsge <- "Hello, Teiwaz!" write(messsge)
Hello, Teiwaz!
Data Type
In Teiwaz, there are 9 data types:
- Numbers, which includes all real numbers, include integers and floats.
- Strings, just mentioned before.
- F-string is a formatted string, which you can simply add a f before the string, and then you can include a variable in your string.
- R-string is a raw string that does NOT support any escape.
- Logical values, which can only be True or False.
- Array, which is same as array in real Python.
- Tuple.
- Dictionary.
- Undefined type, including all exceptions, "UNDEF" and None.
- Try to convert UNDEF into string results in that you get Rickrolled.
All variable's initial value is UNDEF, and you can't access a variable with value of UNDEF.
Operations
You will always get a float number when you're dividing two numbers.
In all other operations, the result will be float if one of operand is float.
However, floating-point operations can sometimes lead to some funny results:
Teiwaz> 0.1 + 0.2 0.30000000000000004 Teiwaz>
That's very common, but it got fixed in 2.0 version.
Constants
As we said, the variable name CAN be all-uppercase, but we don't recommend to do so, because most of people use it as a constant, such as, π.
Comments
# This line is a comment. The interpreter will ignore it. """ This is a document. The interpreter will ignore it, too. """
Array
An array refers to a series of values enclosed in square brackets. You can use an array to create an alphabet chart, a range of numbers, an array of family members, or even an array of all the users on a website.
Index
As an ordered data type, arrays allow indexing. You just need to enclose an index in square brackets after the array name, and Teiwaz will find the element corresponding to that index!
Index starting with 0
In Teiwaz, the only thing you need to pay attention to is that indexing starts from 0, not 1 (1 represents the second element).
Negative index
Of course, Teiwaz supports negative indexing, which means that when you try to access the (-n)th element, Teiwaz will return the nth element from the end. For example, the -1st element is the last one, the -2nd is the second-to-last, and so on.
Access every value in array
Assume that we have a list of users, then we want to greet the first user:
#array.twz users <- ["KELLY", "Albert", "samuel", "MIKE", "pEtEr", "StEvE"] greeting_message <- f"Hello, {users[0].title()}!" write(greeting_message)
Hello, Kelly!
That's strange. Our definition for the first username is all uppercase, but why does it appear as properly capitalized when output?
Appending, Modifying and Deleting
Actually, this is not surprising. This is a technique for handling strings: title case. In title case, the first letter of each word is capitalized, which means that whenever a whitespace character (such as a newline, tab, space, etc.) is detected, the next character will be in uppercase if it has an uppercase form.
You can also make the string into all-uppercase form or all-lowercase form, thus we can modify the program into this:
#array.twz spare <- ["KELLY", "Albert", "samuel", "MIKE", "pEtEr", "StEvE"] users <- spare[:] new_user <- "VINCENT" for user in users: user <- user.lower() if new_user.lower() not in users: spare.append(new_user) users <- spare[:] write(f"The user account \"{new_user.title()}\" was created.\n\nHello, {users[-1]}!")
Or, we can also insert a new user:
#array.twz spare <- ["KELLY", "Albert", "samuel", "MIKE", "pEtEr", "StEvE"] users <- spare[:] new_user <- "VINCENT" for user in users: user <- user.lower() if new_user.lower() not in users: spare.insert(0, new_user) users <- spare[:] for user in users: user <- user.lower() write(f"The user account \"{new_user.title()}\" was created.\n\nHello, {users[-1]}!")
Or, if Samuel deleted his account:
#array.twz spare <- ["KELLY", "Albert", "samuel", "MIKE", "pEtEr", "StEvE", "VINCENT"] users <- spare[:] leaving_user <- "samuel" for user in users: user <- user.lower() if new_user.lower() not in users: spare.remove(leaving_user) users <- spare[:] for user in users: user <- user.lower() write(f"Goodbye, {leaving_user.title()}!\n\nThe user account \"{leaving_user.title()}\" was deleted.")
Or, if we want to get if Kelly was logged in or not:
#array.twz spare <- ["KELLY", "Albert", "MIKE", "pEtEr", "StEvE", "VINCENT"] users <- spare[:] for user in users: user <- user.lower() if "kelly" in user: z <- spare.pop(0) write(f"The user {z.title()} is logging on right now.") spare.insert(0, z) z <- UNDEF
Or, if we want to get the alphabetical form of the user list:
#array.twz spare <- ["KELLY", "Albert", "MIKE", "pEtEr", "StEvE", "VINCENT"] users <- spare[:] for user in users: user <- user.lower() users.sort() # This will change the array forever! write(users)
Or, if we just want to search but not modify:
#array.twz spare <- ["KELLY", "Albert", "MIKE", "pEtEr", "StEvE", "VINCENT"] users <- spare[:] for user in users: user <- user.lower() write(sorted(users))
Or, if we want to get number range from 10 to 1:
#array.twz s <- array(range(1, 11)) s.reverse() # This will permanently reverse s, but it can be restored to its original order at any time by reversing it again. write(s)
For-loop
We've talked about for-loop before. Now, we will go deeper on the for-loop.
As an iterative loop, this is the syntax of for-loop:
for item in container: code
Unnecessary indentation
Indentation is just a tool used to distinguish code blocks. If you mistakenly indent a line of code that doesn't require indentation, then:
#hello.twz message <- "L'internationale, sera le genre humain" write(message)
Program failed to run. ExceptionResume(first one is oldest one): | Error occured in "hello.twz", at line 3, in __main__: | write(messsge) | ~~~~ IndentationFault: The indentation was unnecessary and unexpected.
But sometimes, error indentation will just results in “听取WRONG ANSWER声一片”.
Intervals
We can use "range" to produce a head-opened interval(complete opened interval is made of "interval" and closed is made of "section"). This is how it be used:
k <- array(interval(1, 10)) write(min(k) + max(k))
In this time we will get 11 because kmin + kmax = 1 + 10 = 11.
And we can also let Teiwaz interpret an array by itself:
k <- [value^2 for value in interval(1, 100)] write(k)
This will output all the square numbers from 12 to 1002.
Slice
You may also put a:b:c in the subscript bracket to get a slice from ath element(included) to bth element(not included) with step of c.
Tuple
A tuple is actually an immutable list; you cannot directly access, add, or delete its elements. However, you can directly rebuild the tuple to achieve the purpose of modifying elements. It is parenthesed, so a tuple with only one element should be represented as (a, )
.
Conditional Control Flow
As a selective code structure, it needs to take a condition and then determine whether it is met. If the condition is met, it executes a certain piece of code; otherwise, it executes another piece of code or does nothing.
if condition: code else if condition: code else: code
Logical Operations
We can use logical AND, logical OR, logical NOT, and logical XOR to connect two conditions. Among them, logical AND requires both conditions to be true to return true; logical OR requires at least one of the two conditions to be true to return true; logical NOT checks whether a condition is NOT true; and logical XOR requires that only one of the two conditions is true to return true.
Keyword in
This can check that if an item is in array.
For example, we have a list of admins, and we want to check if a user is admin, then send a greeting message to him/her/them.
#check.twz admins <- ["TrustedInstaller", "SYSTEM", "Andrew", "Benjamin", "Carolina", "David", "Frederich", "Mike", "Victoria"] user <- "Ivan" if user in admins: write(f"Hello, {user}! Would you like to see a status report?") else: write(f"Hello, {user}! Welcome back to our website!")
Checking special values
Suppose there is a pizza shop and a customer wants a pizza, but unfortunately, one of the toppings they requested is out of stock! Now we're in trouble, how should we handle this?
We have already talked about constructing expressions using if-elseif-else statements. Now is the time for conditional control flow to show its power.
#pizza.twz requested_toppings <- ["mushroom", "green peppers", "extra cheese"] for vffdshgbgb in requested_toppings: # Just for joke if vffdshgbgb = "green peppers": write("Sorry, we're out of green peppers right now.") else: write(f"Adding {vffdshgbgb}.") write("\nFinished to make your pizza!")
OK, now the program can output that green peppers is out of stock now.
Checking special values (2)
We now have three lists in our hands: one is a list of all individuals entering Country X from Country Y, one is a list of spies sent from Country Y to Country X, and the other is a list of spies that Country X has sent to Country Y. Note that the two spy lists may overlap, and these individuals are referred to as "double agents." Now, as guardians of Country X, we want to intercept all spies from Country Y while allowing ordinary people and double agents to pass freely.
#spy.twz people <- ["Alice", "Bob", "Carolina", "David", "Eve", "Frederich", "Gabriel", "Harry"] spies_Y <- ["Alice", "Bob", "Carolina", "David"] spies_X <- ["Alice", "Eve", "Harry", "Issac", "Mike"] # Note: Issac did not return to Country X, and Mike did not leave Country X. enemy_spies <- [] for person in people: if person in spies_Y: if person in spies_X: pass # This will do nothing else: enemy_spies.append(person) else: pass if enemy_spies.length() == 0: write("No enemy spy!") else: write(enemy_spies)
Dictionary
Actually, to be frank, a dictionary is just an array full of key-value pairs. The only difference is that a dictionary is enclosed in curly braces. (L. O. L. )
For example, if we have a virtual character "Jack", and we want to save his data, then:
k <- {"name": "Jack", "gender": False, "age": 14, "languages": ["English", "Latin", "Romanian"]} write(f"Hi everyone! I'm {k['name']}. I'm a {k['age']}-year-old {'girl' if k['gender'] else 'boy'}, and I can speak ", end <- "") for language in k['languages']: write(language, end <- ("." if (language.index() == k['languages'].length() - 1) else (" and " if (language.index() == k['languages'].length() - 2) else ", ")))
And also we can search for a key-value bind, but it won't throw error if nothing is searched(unless you let it return error):
k <- {"name": "Jack", "gender": False, "age": 14, "languages": ["English", "Latin", "Romanian"]} name <- k.get('name', str(UNDEF)) write(name)
In this case, it will output his name, but what if we accidentally misspelled it?
k <- {"name": "Jack", "gender": False, "age": 14, "languages": ["English", "Latin", "Romanian"]} name <- k.get('mame', str(UNDEF)) write(name)
In this time, the output:
We're no strangers to love You know the rules and so do I (do I) A full commitment's what I'm thinking of You wouldn't get this from any other guy I just wanna tell you how I'm feeling Gotta make you understand Never gonna give you up Never gonna let you down Never gonna run around and desert you Never gonna make you cry Never gonna say goodbye Never gonna tell a lie and hurt you We've known each other for so long Your heart's been aching, but you're too shy to say it (say it) Inside, we both know what's been going on (going on) We know the game and we're gonna play it And if you ask me how I'm feeling Don't tell me you're too blind to see Never gonna give you up Never gonna let you down Never gonna run around and desert you Never gonna make you cry Never gonna say goodbye Never gonna tell a lie and hurt you Never gonna give you up Never gonna let you down Never gonna run around and desert you Never gonna make you cry Never gonna say goodbye Never gonna tell a lie and hurt you We've known each other for so long Your heart's been aching, but you're too shy to say it (say it) Inside, we both know what's been going on (going on) We know the game and we're gonna play it I just wanna tell you how I'm feeling Gotta make you understand Never gonna give you up Never gonna let you down Never gonna run around and desert you Never gonna make you cry Never gonna say goodbye Never gonna tell a lie and hurt you Never gonna give you up Never gonna let you down Never gonna run around and desert you Never gonna make you cry Never gonna say goodbye Never gonna tell a lie and hurt you Never gonna give you up Never gonna let you down Never gonna run around and desert you Never gonna make you cry Never gonna say goodbye Never gonna tell a lie and hurt you
Haha, you got Rickrolled!
Traverse, insert, delete, and modify key-value pairs
We can also modify on a dictionary, such as, if we want to insert a new word into our biological data:
bio <- {"Phagocyte": "Absorb nutrients from the outside world", "Flagellocyte": "Move the organism using flagella", "Photocyte": "Convert light energy into the chemical energy in organic matter"} bio['Lipocyte'] <- "It has a layer of fat that makes its lifespan longer, but it leaves behind a lump of nutrients coated with fat when it dies" bio['Devorocyte'] <- "Enriches itself by seizing the energy from the cells it comes into contact with through the cell membrane" bio['Flagellocyte'] <- "Allows a life form to swim with a specified force using its flagella (consuming energy corresponding to that force), but swims hardly in environments with excessive friction" for k, v in bio.items(): write(k, "\n\t", v)
While-loop and User Input
read()
The function in the title pauses the program until the user finishes inputting and presses the Enter key. For example,
# greet.twz name <- read(prompt <- "May I have your name? >>> ") write(f"Hello, {name}!")
Type conversion
You can also change a variable into another type, simply by enclosing the variable in parentheses and then adding the type you want in front.
For example, this is an A + B problem:
# A_plus_B.twz a <- int(read(prompt <- "Please enter an addend: ")) b <- int(read(prompt <- "Please enter another addend:")) write(f"Their sum is {a + b}.")
While-loop and break
Let's write a cat program:
# cat.twz active <- True while active: x <- read(prompt <- "Please input something, and I'll output it for you:") if x != "": write(x) else: write("Thanks for using!") active = False
This program will ask for user input and print it out if it is not empty. Note that Teiwaz considers all null values (such as the number 0, empty strings, empty arrays, empty dictionaries, empty tuples, None, logical false, etc.) as false conditions, while other values are considered true conditions, so we can simply modify the program into this:
# cat.twz while True: x <- read(prompt <- "Please input something, and I'll output it for you:") if x: write(x) else: write("Thanks for using!") break
Trapped in an endless cycle
Every loop should have an exit condition; otherwise, the program will get stuck and be unable to continue executing the subsequent code normally. For example, suppose we have a program that counts from 1 to 10:
# counter.twz x <- 1 while x <= 10: write(x) x <- x + 1
But what if your mother calls you to eat while you are in the middle of coding?
# counter.twz x <- 1 while x <= 10: write(x)
In this situation, the program will keep outputting 1 over there and do nothing else. If you are still sitting in front of your computer at this time, you might have two possible outcomes: either you close the window and go eat, or you stay in front of the computer and get scolded by your mother.
continue
We can also use continue to skip over current round of loop, such as:
# counter.twz x <- 1 while x <= 10: x <- x + 1 if x % 2 = 0: continue write(x)
Functions
Function is a subroutine that accepts several arguments(or no argument) and with a name(we call a function without name "lambda"). Function is used to do a specified things without a BIG amount of codes.
Define a function
# greeting_user.twz function greet_user(): """Greet the user with the simplest greeting.""" write("Hello!") greet_user()
We use the function keyword to define a function. In this example, we call it greet_user. Then, we enclose the parameter list in parentheses, even though this function does not take any parameters. All the indented code following the definition statement is called the function body.
We also use sextuple quotes(“““”””) or triple quotes(‘‘‘’’’) to write documentation, indicating what the function is for. (This will generate a multiline string, but it is more commonly used as a comment)
Send message to the function
Let's open the greeting_user.twz, then modify the program into this:
# greeting_user.twz function greet_user(username): """Greet the user with the simplest greeting.""" write(f"Hello, {username}!") greet_user("Raymond")
In this program, the greeting function now accepts a username and then greets the user. Here, 'username' is a formal parameter, while the 'Raymond' we pass to the function is the actual argument.
Positional Arguments
The simplest way to match actual parameters with formal parameters is by the order in which they are passed. However, you must pay attention to the order, otherwise you might end up with a result like 'a user named "Confirmed User" with the category "Harry".' This is funny, but it's not really funny. Next, we will see how to solve this problem.
Keyword Arguments
Another way is to directly pass the arguments to be defined into the corresponding parameters; this technique is called keyword arguments. In this case, you do not need to pay attention to the order of the arguments, but you must pay attention to the names of the parameters.
Any number of arguments
In some cases, we may need to pass a large number of arguments, but we don't know how many arguments we might pass. At this time, we can use something like '*args', which allows the function to create an empty tuple and package all the arguments into this tuple. In the previous example, we learned that the write function can output multiple values consecutively, so here is the declaration of the write function:
function write(*args, **kwargs, sep <- ' ', end <- '\n')
Any number of keyword arguments
Of course, we can also use something like '**kwargs' to allow a function to accept any number of keyword arguments. For example, suppose we have a user, and we know their first(, middle) and last name, as well as their password, but we don't know other data. What should we do?
# construct_userdata.twz function build_user(first, last, middle <- "", password, **info): info['first'] <- first info['last'] <- last info['middle'] <- middle info['password'] <- password return info x = build_user("Andy", "Noltas", "", "Anoltas1145141919810!!!", permission <- "confirmed user", edit_num <- 7108, email <- "anoltas@cronos.com", register_date <- "2018-10-3") print(x)
Modules and Imports
The greatest advantage of using functions is that they separate code blocks from the main program. We can go even further by passing the function as an independent file into another file.
Import whole module
To import a module, we use "include". For example,
# build.twz function build_user(first, last, middle <- "", password, **info): info['first'] <- first info['last'] <- last info['middle'] <- middle info['password'] <- password return info
# main.twz include "build.twz" x = build_user("Andy", "Noltas", "", "Anoltas1145141919810!!!", permission <- "confirmed user", edit_num <- 7108, email <- "anoltas@cronos.com", register_date <- "2018-10-3") write(x)
As a module to be imported, Teiwaz must confirm whether it is in the standard library directory or in the current workspace. If not, then you may got this exceptionresume:
Program failed to run. ExceptionResume(first one is oldest one): | Error occured in "main.twz", at line 2, in __main__: | include "settings.twz" | ~~~~~~~~~~~~ FileNotFound: Failed to find the module that needs to be imported
Import Part of Module
Also we can just import a part from module. Here is an example:
# build.twz function build_user(first, last, middle <- "", password, **info): info['first'] <- first info['last'] <- last info['middle'] <- middle info['password'] <- password return info
# main.twz include build_user from "build.twz" x = build_user("Andy", "Noltas", "", "Anoltas1145141919810!!!", permission <- "confirmed user", edit_num <- 7108, email <- "anoltas@cronos.com", register_date <- "2018-10-3") write(x)
Nickname for Module
We can also name a module with an alias during the main program. For example,
# main.twz include randint from "random.twz" as rdi write(rdi(1, 6))
As a tag, the alias you give to a module should also follow the naming rules of variable names.
Note, if you write something like include * from "system.twz"
, then it will import all functions, data and classes into your program, but not entire module.
OOP
Object-oriented programming is a good thing. It allows you to describe an entire class with just a few lines of code to create custom 'data types,' and you can also perform inheritance and overriding between different 'data types.'
Create a class
Using classes, we can almost simulate everything. For example, if we want to represent all the dogs in the world, or all the users of a website, all the countries and regions on Earth, or all the functions of a data type, we can directly define a class.
For example, for a country, it must have a name, a population, a certain area, and a capital. Then we can write this into our program:
# states.twz class Country: """Simulate a country""" def __init__(this, name, pop, area, cap, fd): this.name, this.pop, this.area, this.cap, this.fd <- name, pop, area, cap, fd def introduction(this) write(f"This is a country named {this.name}, with a population of {this.pop}(approximately) people and an area of {this.area} km2.", f"Its capital is at {this.cap}. It was found on {this.fd}.") pakistan <- Country.__init__("Islamic Republic of Pakistan", 2_4100_0000, 88_0254, "Islamabad", "March 23, 1956") pakistan.introduction()
In this example, we created a 'Country' class and instantiated this class (at least in the data flow) — the Islamic Republic of Pakistan.
Method and Attributes
Functions defined in a class are called methods, and variables are called attributes. To access a method or attribute, you need to put a dot after the instance name and then write the corresponding method or attribute name.
In this way, we can create a large number of instances. For example, let's create another instance—the Republic of India.
# states.twz class Country: """Simulate a country""" def __init__(this, name, pop, area, cap, fd): this.name, this.pop, this.area, this.cap, this.fd <- name, pop, area, cap, fd def introduction(this) write(f"This is a country named {this.name}, with a population of {this.pop}(approximately) people and an area of {this.area} km2.", f"Its capital is at {this.cap}. It was found on {this.fd}.") pakistan <- Country.__init__("Islamic Republic of Pakistan", 2_4100_0000, 88_0254, "Islamabad", "March 23, 1956") pakistan.introduction() write() india <- Country.__init__("Republic of India", 14_4000_0000, 298_0000, "New Delhi", "August 15, 1947") # The territorial area does not include the South Tibet region and the Kashmir region. india.introduction()
Code block for creating class
class YourClassName: """Document""" def __init__(this, *args, **kwargs): # Attributes def method_name(this) # Method body class AnotherClassName(YourClassName): """Document""" def __init__(this, *args, **kwargs): # Inheritance and Overriding def method_name(this) # Method body
File I/O and Exceptions
Now, you have acquired a lot of knowledge about Teiwaz. You can write many programs. Next, we will learn about file input/output and exceptions.
Read the contents of the file
The amount of data that a text file can store is truly astonishing. You could use a single file to store the entire text of 'A Midsummer Night's Dream,' the first billion digits of pi, an encyclopedia, a complete list of a website's user data, or just a bunch of meaningless gibberish.
For example, let's say that we have a poem by Qu Yuan:
帝高阳之苗裔兮,朕皇考曰伯庸。 摄提贞于孟陬兮,惟庚寅吾以降。 皇览揆余初度兮,肇锡余以嘉名: 名余曰正则兮,字余曰灵均。 --snip--
This program reads the content above and output it onto the screen.
# file.twz with open("离骚.txt") as f: contents <- f.read() write(contents)
Now we should get this output:
帝高阳之苗裔兮,朕皇考曰伯庸。 摄提贞于孟陬兮,惟庚寅吾以降。 皇览揆余初度兮,肇锡余以嘉名: 名余曰正则兮,字余曰灵均。 --snip--
But if we look at the last rows of output:
--snip-- 乱曰:已矣哉! 国无人莫我知兮,又何怀乎故都! 既莫足与为美政兮,吾将从彭咸之所居!
The file is output very accurately, but there is an extra blank line at the end representing EOF. To remove the blank line, we can use the rdelblank method of the string to remove trailing whitespace characters, whether they are tabs, newlines, or spaces.
We can also just read a line, such as:
# file.twz with open("离骚.txt") as f: for line in f: write(line)
We will found that there are MUCH of empty lines.
帝高阳之苗裔兮,朕皇考曰伯庸。 摄提贞于孟陬兮,惟庚寅吾以降。 皇览揆余初度兮,肇锡余以嘉名: 名余曰正则兮,字余曰灵均。 --snip--
However, not only can we read, we can also write to or overwrite files.
Character | Meaning |
---|---|
r | Read-only |
r* | Read-write |
rb | Binary read |
rb* | Binary rw |
w | Write-only |
w* | Write-read |
wb | Binary write |
wb* | Binary rw |
a | Appendix-write |
a* | Appendix-read |
ab | Binary append. |
ab* | Binary append. rw |
Exception Handling
Sometimes your code can leave Teiwaz confused. At such times, Teiwaz will record what went wrong using an undefined data type called an exception. If you handle the exception properly, Teiwaz will either continue execution or revert to a safe state. If not, Teiwaz will stop working and display a bunch of Exceptionresume messages.
This list outlines some common mistakes:
Exception Name | Why? |
---|---|
SyntaxError | There is a syntax error in the code. |
ValueError | An error occurred with the incoming or outgoing value. |
NameError | Try using an undefined identifier. |
IndentationFault | Did not indent according to the specified code format. |
FileNotFound | File not found in the specified namespace. |
TypeError | There was a problem during type conversion. |
MathError | A very foolish arithmetic error occurred, such as trying to divide 5 by 0. |
RuntimeError | Strange behaviors that cause stack overflow, such as infinite recursion, have appeared. |
InternalSystemError | Problems may occur during running, compiling, or interpreting, or there may be issues with the environment during installation. If you encounter this situation, please reinstall Teiwaz. |
MemoryFault | When the code is executed, a portion of memory is always reserved. This situation is likely because the memory reserved by the code has been exhausted. |
For example, we have a division calculator.
# division.twz write("A simple division calculator. Enter q to exit.") while True: dividend <- read("Please input the dividend: ") if dividend == "q": break divisor <- read("Please input the divisor: ") if divisor == "q": break try: answer <- dividend / divisor catch MathError: write("You big fool! 0 cannot be used as a divisor!") else: write(f"The quotient of these two numbers is {answer}.") finally: write("Performed a division operation.\n")
JSON
In timeline 284436, JSON is called ZLON (JavaScript is called ZephyrLang there).
Using JSON to store data is very useful! Sometimes, your program is closed, but you need to save your data (usually, the data is lost when the program is closed). At this time, you can use a JSON file to save it, for example, the high score of a video game you are playing.
Testing Your Code
Testing your code allows you to know what problems your code has. To test code, Teiwaz provides the 'asserttest' standard library.All standard libraries are treated as Teiwaz programs.
In this standard library, it provides a very effective testing tool: assertions. If the assertion fails, the program will stop running and then output an Exception resume, but it only indicates that the assertion did not hold.
In all tests, if the code is correct and the assertions hold, the output will be a dot. If there is an exception in the code, the output will be an 'E' for Exception. If an assertion fails, the output will be an 'F' for False.
Code block for testing:
include "asserttest.twz" class YourTestName(asserttest.CodeTesting): def setup(this): # Setup def test(this): # Assertion Test