Brainfuck interpreter in Nimrod - interpreter

I am toying with nim (at the time of writing still called nimrod), by writing a Brainfuck interpreter in the language. Without loops implemented, I have:
import os, unsigned
const RamSize = 200
type
TRam = array[0..RamSize, int]
var
ram : TRam
ip : int = 0
dp : int = 0
proc readCode(path: string) =
var
f : TFile = open(path)
i : int = 0
while i < RamSize and not EndOfFile(f):
ram[i] = ord(readChar(f))
inc(i)
proc main(path: string) =
readCode(path)
while ip < RamSize:
case chr(ram[ip])
of '>' : inc dp
of '<' : dec dp
of '+' : inc ram[dp]
of '-' : dec ram[dp]
of '.' : write stdout, chr(ram[dp])
else : nil
inc(ip)
echo()
if paramcount() == 1: main(paramstr(1))
else: echo("usage: bfrun PATH")
It compiles successfully, but when I throw an input at it like:
>
+++++ +++++
+++++ +++++
+++++ +++++
+++++ +++++
+++++ +++++
+++++ +++++
+++++ .
Which should print the character 'A' it returns 'N.' Any ideas?

If I understand this correctly, it looks like dp is set to 1, and then ram[dp] is incremented 65 times. But ram[dp], aka ram[1], starts out holding the second character of the program, which is a carriage return character (ASCII 13). A is ASCII 65, N is ASCII 78, and 65 + 13 is 78.
Set dp to somewhere outside of program space before you start incrementing the memory cell -- or use separate RAM to hold the program.

Related

Specman - add bits in the beginning and end of list of bit

I have the following list of bit which contains 8 bits (input to function):
bs: list of bit;
I have the following struct:
struct uart_frame_s like any_sequence_item {
%start_bit : bit;
data_size : uint;
%data[data_size] : list of bit;
%stop_bit : bit;
keep soft start_bit == 0;
keep soft stop_bit == 1;
keep soft data_size == 8;
};
I have to execute the following:
unpack(packing.low, bs, current_frame);
The problem that bs size is 8, but current frame contains 10 bits....
So how can I add bits in the beginning and end of list of bit ('0' in the beginning and '1' in the end).
Or alternatively verify that the bs will unpack to 1-8 bits in current frame.
if you want to pack the bs into the frame data field, you can -
unpack(packing.low, bs, current_frame.data);

Is there a way to simplify incremental calculations in acrobat?

Other than using a long string of if statements is there a way to program an acrobat text box to incrementally calculate based on variables entered into an other text box?
Here is what I have.
var v = this.getField("FixNum").value;
if (v == "1")
{
event.value = 84 ;
}
else if (v == "2")
{
event.value = 88 ;
}
else if (v == "3")
{
event.value = 92 ;
}
else
{
event.value = "";
}
As you can see this will get cumbersome because this goes from 1 - 9 in this pattern where 9 = 116, then 10 - 100 where 10 = 135. After 100 the pattern is 495 + 6 for every unit i.e. 101 = 501. I hope someone can understand this because I can't think of another way to ask!
Several possibilities:
• If you can come up with a formula, it would be simplest.
• If the value pairs are arbitrary, you might create a lookup table (in form of an array).
• If the input numbers are (more or less) consecutive integers, you can work with a simple array, where the index is the input number, and the element with that index number is the output number.
• If it is more complicated, you would have to create a 2-dimensional array, where each element is an array of input and output number.
• If you are looking for a simple replacement of if…else if statements, you can use the switch… statement, which would work well for totally arbitrary value pairs.
Update, following the comment by OP:
According to a comment by the OP, the input numbers are consecutive, which means that the third point above would be the method of choice. For that, proceed as follows:
Create a document-level script (the name does not matter):
var myPricesArr = [0, 12, 15, 17, 23, 27, 30, 33] ;
alternate possibility:
var myPricesArr = new Array() ;
myPricesArr[0] = 0 ;
myPricesArr[1] = 12 ;
myPricesArr[2] = 15 ;
myPricesArr[3] = 17 ;
myPricesArr[4] = 23 ;
myPricesArr[5] = 27 ;
myPricesArr[6] = 30 ;
myPricesArr[7] = 33 ;
Both variants are equivalent, but the second one is easier to maintain, but requires more typing…
Create a text field named "numFixts", formatted as number, no decimals, maybe with a maximum value (to protect the form from failing).
Create a text field named "fixtsAmt, formatted as number. In the Calculate event of this field add the following JavaScript:
event.value = myPricesArr[this.getField("numFixts").value] ;
And that should do it.

String can't be split by Tab or Space. Which character is this?

I have this string which looks like this:
613 3503||0 82 1 49 1 1950 63543 11301 3 CORP-A1 1656.06 150 0 N 82.8 198.72 12.42 N 0 0 0 N Y 1
However, when I string split it by either TAB or SPACE, it does not split via Tab or space. It still outputs as the whole thing.
I tried the following:
= fromVisMtext.Text.Split(vbTab)
= fromVisMtext.Text.Split(" ")
Also, here at stack overflow when I pasted said string, it isn't delimited and is connected with each other.
6133503||0821491195063543113013CORP-A11656.061500N82.8198.7212.42N000NY1
The string I've pasted above was mine that I added white spaces manually, since here StackOverflow removes said delimiters.
Also, said string is from the VisM control of Intersystems Cache.
How can split this string by either Tab or Space? It doesn't seem to be either, but the data is definitely delimited by a white space or tab something.
EDIT here is the result of Dim theGlobals = String.Join(" ", fromVisMtext.Text.Select(Function(ch) Microsoft.VisualBasic.AscW(ch).ToString("x4")))
In general case (space, tab, non breaking space etc. separators) you can try split by any white space, e.g.:
String source = #"613 3503||0 82 1 49 1 1950 63543 11301 3 CORP-A1 1656.06 150 0 N 82.8 198.72 12.42 N 0 0 0 N Y 1";
var result = Regex
.Split(source, #"\s")
.Where(item => !String.IsNullOrEmpty(item));
//.ToArray(); // <- if you want to materialize
// 613
// 3503||0
// 82
// 1
// ...
// N
// Y
// 1
Console.Write(String.Join(Environment.NewLine, result));
If you´re sure that separators can be space (' ') or tab ('\t') only you can just split:
var result = source.Split(new Char[] { ' ', '\t' },
StringSplitOptions.RemoveEmptyEntries);

how to generate multi-line comment

In stringtemplate-4, how to generate a multi-line comment? For example, the template is like this (the comment's start and end are in some other template):
test(DESCRIPTION) ::= <<
*
* <DESCRIPTION>
*
>>
And DESCRIPTION is a long string, and may also contain line-feeds in it, like:
"This is a small description of the program, with a line-width of 50 chars max, so the line is split.\nFinal line."
So we want the output string like:
*
* This is a small description of the program,
* with a line-width of 50 chars max, so the
* line is split.
* Final line.
*
It looks like you're wanting to do a couple of things here- put the description on a line which starts
with an asterisk, but if there's a linefeed or the length is greater than 50, put that on
a separate line.
First off, I'd split the description up in the view model prior to passing it to the template, based on line feeds and the length.
I'd then make a small change to the template to separate each item in the array with
a newline and an asterisk.
Here's the group file test.stg:
group test;
description(lines) ::= <<
*
* <lines; separator="\n* ">
*
>>
I'm not sure which language you're using in the view model, but here's some Java:
public static void main(String[] args) {
STGroup templates = new STGroupFile("test.stg");
String description = "This is a small description of the program, with a line-width of 50 chars max, so the line is split.\nFinal line.";
// we add two characters at the start of each line "* " so lines can now
// be only 48 chars in length
description = addLinebreaks(description, 48);
String lines[] = description.split("\\r?\\n");
ST descTemplate = templates.getInstanceOf("description");
for (String line : lines)
{
descTemplate.add("lines", line);
}
System.out.println(descTemplate.render());
}
// used to add line breaks if the length is greater than 50
// From this SO question: http://stackoverflow.com/questions/7528045/large-string-split-into-lines-with-maximum-length-in-java
public static String addLinebreaks(String input, int maxLineLength) {
StringTokenizer tok = new StringTokenizer(input, " ");
StringBuilder output = new StringBuilder(input.length());
int lineLen = 0;
while (tok.hasMoreTokens()) {
String word = tok.nextToken()+" ";
if (lineLen + word.length() > maxLineLength) {
output.append("\n");
lineLen = 0;
}
output.append(word);
lineLen += word.length();
}
return output.toString();
}
The output I got was:
*
* This is a small description of the program,
* with a line-width of 50 chars max, so the line
* is split.
* Final line.
*
which looks slightly different to your example, but does meet the 50 char limit. I guess you can play around with it until it matches your requirements.

formating string to hex and validate

I have an application that accepts hex values from a C++/CLI richtextbox.
The string comes from a user input.
Sample input and expected output.
01 02 03 04 05 06 07 08 09 0A //good input
0102030405060708090A //bad input but can automatically be converted to good by adding spaces.
XX ZZ DD AA OO PP II UU HH SS //bad input this is not hex
01 000 00 00 00 00 00 01 001 0 //bad input hex is only 2 chars
How to write function:
1. Detect if input is good or bad input.
2. If its a bad input check what kind of bad input: no spaces, not hex, must be 2 chars split.
3. If its no spaces bad input then just add the spaces automatically.
So far I made a space checker by searching for a space like:
for ( int i = 2; i < input.size(); i++ )
{
if(inputpkt[i] == ' ')
{
cout << "good input" << endl;
i = i+2;
}
else
{
cout << "bad input. I will format for you" << endl;
}
}
But it doesn't really work as expected because it returns this:
01 000 //bad input
01 000 00 00 00 00 00 01 001 00 //good input
update
1 Check if input is actually hex:
bool ishex(std::string const& s)
{
return s.find_first_not_of("0123456789abcdefABCDEF ", 0) == std::string::npos;
}
Are you operating in C++/CLI, or in plain C++? You've got it tagged C++/CLI, but you're using std::string, not .Net System::String.
I suggest this as a general plan: First, split your large string into smaller ones based on any whitespace. For each individual string, make sure it only contains [0-9a-fA-F], and is a multiple of two characters long.
The implementation could go something like this:
array<Byte>^ ConvertString(String^ input)
{
List<System::Byte>^ output = gcnew List<System::Byte>();
// Splitting on a null string array makes it split on all whitespace.
array<String^>^ words = input->Split(
(array<String^>)nullptr,
StringSplitOptions::RemoveEmptyEntries);
for each(String^ word in words)
{
if(word->Length % 2 == 1) throw gcnew Exception("Invalid input string");
for(int i = 0; i < word->Length; i += 2)
{
output->Add((Byte)(GetHexValue(word[i]) << 4 + GetHexValue(word[i+1])));
}
}
return output->ToArray();
}
int GetHexValue(Char c) // Note: Upper case 'C' makes it System::Char
{
// If not [0-9a-fA-F], throw gcnew Exception("Invalid input string");
// If is [0-9a-fA-F], return integer between 0 and 15.
}