I've been trying to convert a python project to nxc using the IDE: Brixc Command Center, so that it'll read a text file and split down the information into components where it can process it.
The main road block for me is the split string method which I cannot find/figure out.
in python it would be easy like Data1 = RawData.split("\n") where it would split it into a array and where I can sort through it like this:
Data1[nth position in array][character in nth position in selected value in array]
I tried doing repeating the same method in nxc but it doesn't work
1: #import "RawData.txt" Data0
2: string Data1[];
3: "task main(){
4: Data1 = Data0.split("\n");
5: if(Data1[1][0]=="a"){
6: TextOut(10,10,"its an a!");
7: }else{
8: TextOut(10,10,Data1[1][0]);
9: }
10: Wait(5000);
11:}
12:
the output should be the display of the first character of the second line in this case. surprisingly not, it doesn't work. and it spits out a few errors (I'm new to nxc after all).
line 3: Error: Datatypes are not compatible
line 3: Error: ';' expected
line 3: Error: Unmatched close parenthesis
line 4: Error: Unmatched close parenthesis
Just change the "a" to 'a'.
1: #import "RawData.txt" Data0
2: string Data1[];
3: task main(){
4: Data1 = Data0.split("\n");
5: if(Data1[1][0]=='a'){
6: TextOut(10,10,"its an a!");
7: }else{
8: TextOut(10,10,Data1[1][0]);
9: }
10: Wait(5000);
11:}
12:
" denotes a string (which is an array of characters) where as ' denotes a single character.
Related
I using Jacoco 0.8.6 and I have an enum with 3 values.
I have this when shown on the image below and I have a test for each branch but Jacoco is still saying that I am missing a branch, also my var is non-null. What is wrong?
JaCoCo performs analysis of bytecode. For Example.kt
object Example {
var type: Type = Type.SETUP_LOGIN
set(value) {
field = value
when (value) {
Type.SETUP_LOGIN -> nop()
Type.CHANGE_PIN -> nop()
Type.CHANGE_FINGERPRINT -> nop()
}
}
fun nop() {
}
enum class Type {
SETUP_LOGIN, CHANGE_PIN, CHANGE_FINGERPRINT
}
}
compiled by
kotlinc-1.4.30/bin/kotlinc Example.kt
execution of
java -v -p Example.class
shows following bytecode for setType method
public final void setType(Example$Type);
descriptor: (LExample$Type;)V
flags: ACC_PUBLIC, ACC_FINAL
Code:
stack=2, locals=2, args_size=2
0: aload_1
1: ldc #17 // String value
3: invokestatic #23 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
6: aload_1
7: putstatic #11 // Field type:LExample$Type;
10: aload_1
11: getstatic #29 // Field Example$WhenMappings.$EnumSwitchMapping$0:[I
14: swap
15: invokevirtual #35 // Method Example$Type.ordinal:()I
18: iaload
19: tableswitch { // 1 to 3
1: 44
2: 51
3: 58
default: 65
}
44: aload_0
45: invokevirtual #39 // Method nop:()V
48: goto 65
51: aload_0
52: invokevirtual #39 // Method nop:()V
55: goto 65
58: aload_0
59: invokevirtual #39 // Method nop:()V
62: goto 65
65: return
LineNumberTable:
line 4: 6
line 5: 10
line 6: 44
line 7: 51
line 8: 58
line 9: 65
line 10: 65
where as you can see tableswitch has 4 branches and this is exactly what you see in the JaCoCo report.
Looking at such bytecode only (as like JaCoCo does) there is no way to realize that default branch of tableswitch can't be reached - add one more value to enum, without changing anything else, recompile and you'll see exactly the same bytecode for this setType method.
You can use exhaustive
val <T> T.exhaustive: T
get() = this
then
when (value) {
Type.SETUP_LOGIN -> nop()
Type.CHANGE_PIN -> nop()
Type.CHANGE_FINGERPRINT -> nop()
}.exhaustive
I'm checking kotlinc bytecode of capturing lambdas. And trying to understand the reason why resulting bytecode has nop instructions.
kotlinc -jvm-target 1.6 .
private inline fun lambdaCapturing(f: () -> Int): Int = f()
fun main(args: Array<String>) {
lambdaCapturing { 42 }
}
As a result I'm getting
public final class x.y.z.LambdaCaptKt {
private static final int lambdaCapturing(kotlin.jvm.functions.Function0<java.lang.Integer>);
Code:
0: ldc #8 // int 0
2: istore_1
3: aload_0
4: invokeinterface #14, 1 // InterfaceMethod kotlin/jvm/functions/Function0.invoke:()Ljava/lang/Object;
9: checkcast #16 // class java/lang/Number
12: invokevirtual #20 // Method java/lang/Number.intValue:()I
15: ireturn
public static final void main(java.lang.String[]);
Code:
0: aload_0
1: ldc #29 // String args
3: invokestatic #35 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
6: iconst_0
7: istore_1
8: iconst_0
9: istore_2
10: nop
11: nop
12: nop
13: return
}
with several nop instructions in main function.
If I will compile the same code snippet with -Xno-optimize, main function will look like
public static final void main(java.lang.String[]);
Code:
0: aload_0
1: ldc #29 // String args
3: invokestatic #35 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
6: nop
7: iconst_0
8: istore_1
9: nop
10: iconst_0
11: istore_2
12: bipush 10
14: nop
15: goto 18
18: invokestatic #41 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
21: checkcast #16 // class java/lang/Number
24: invokevirtual #20 // Method java/lang/Number.intValue:()I
27: nop
28: goto 31
31: pop
32: return
There are nops as well.
What is the reason to have nops in non-optimised code? (debug info/...)
Is there any reason to have nops in optimized code?
The reason for nops in the bytecode that the Kotlin compiler emits is the possibility for the debugger to put a breakpoint at the closing brace, i.e. after the last statement, of a function or an if-clause and other clauses, and to make it possible to step to those locations. Doing that requires an instruction present in the bytecode that is also marked with the line number.
Some nops are then optimized away if they are redundant, such as when there's already a valid instruction following the last statement instructions.
In perl6 grammars, as explained here (note, the design documents are not guaranteed to be up-to-date as the implementation is finished), if an opening angle bracket is followed by an identifier then the construct is a call to a subrule, method or function.
If the character following the identifier is an opening paren, then it's a call to a method or function eg: <foo('bar')>. As explained further down the page, if the first char after the identifier is a space, then the rest of the string up to the closing angle will be interpreted as a regex argument to the method - to quote:
<foo bar>
is more or less equivalent to
<foo(/bar/)>
What's the proper way to use this feature? In my case, I'm parsing line oriented data and I'm trying to declare a rule that will instigate a seperate search on the current line being parsed:
#!/usr/bin/env perl6
# use Grammar::Tracer ;
grammar G {
my $SOLpos = -1 ; # Start-of-line pos
regex TOP { <line>+ }
method SOLscan($regex) {
# Start a new cursor
my $cur = self."!cursor_start_cur"() ;
# Set pos and from to start of the current line
$cur.from($SOLpos) ;
$cur.pos($SOLpos) ;
# Run the given regex on the cursor
$cur = $regex($cur) ;
# If pos is >= 0, we found what we were looking for
if $cur.pos >= 0 {
$cur."!cursor_pass"(self.pos, 'SOLscan')
}
self
}
token line {
{ $SOLpos = self.pos ; say '$SOLpos = ' ~ $SOLpos }
[
|| <word> <ws> 'two' { say 'matched two' } <SOLscan \w+> <ws> <word>
|| <word>+ %% <ws> { say 'matched words' }
]
\n
}
token word { \S+ }
token ws { \h+ }
}
my $mo = G.subparse: q:to/END/ ;
hello world
one two three
END
As it is, this code produces:
$ ./h.pl
$SOLpos = 0
matched words
$SOLpos = 12
matched two
Too many positionals passed; expected 1 argument but got 2
in method SOLscan at ./h.pl line 14
in regex line at ./h.pl line 32
in regex TOP at ./h.pl line 7
in block <unit> at ./h.pl line 41
$
Line 14 is $cur.from($SOLpos). If commented out, line 15 produces the same error. It appears as though .pos and .from are read only... (maybe :-)
Any ideas what the proper incantation is?
Note, any proposed solution can be a long way from what I've done here - all I'm really wanting to do is understand how the mechanism is supposed to be used.
It does not seem to be in the corresponding directory in roast, so that would make it a "Not Yet Implemented" feature, I'm afraid.
I'm working on a game written in Kotlin and was looking into improving GC churn. One of the major sources of churn are for-loops called in the main game/rendering loops that result in the allocation of iterators.
Turning to the documentation, I found this paragraph:
A for loop over an array is compiled to an index-based loop that does not create an iterator object.
If you want to iterate through an array or a list with an index, you can do it this way:
for (i in array.indices)
print(array[i])
Note that this “iteration through a range” is compiled down to optimal implementation with no extra objects created.
https://kotlinlang.org/docs/reference/control-flow.html#for-loops
Is this really true? To verify, I took this simple Kotlin program and inspected the generated byte code:
fun main(args: Array<String>) {
val arr = arrayOf(1, 2, 3)
for (i in arr.indices) {
println(arr[i])
}
}
According to the quote above, this should not result in any objects allocated, but get compiled down to a good old pre-Java-5 style for-loop. However, what I got was this:
41: aload_1
42: checkcast #23 // class "[Ljava/lang/Object;"
45: invokestatic #31 // Method kotlin/collections/ArraysKt.getIndices:([Ljava/lang/Object;)Lkotlin/ranges/IntRange;
48: dup
49: invokevirtual #37 // Method kotlin/ranges/IntRange.getFirst:()I
52: istore_2
53: invokevirtual #40 // Method kotlin/ranges/IntRange.getLast:()I
56: istore_3
57: iload_2
58: iload_3
59: if_icmpgt 93
This looks to me as if a method called getIndices is called that allocates a temporary IntRange object to back up bounds checking in this loop. How is this an "optimal implementation" with "no extra objects created", or am I missing something?
UPDATE:
So, after toying around a bit more and looking at the answers, the following appears to be true for Kotlin 1.0.2:
Arrays:
for (i in array.indices): range allocation
for (i in 0..array.size): no allocation
for (el in array): no allocation
array.forEach: no allocation
Collections:
for (i in coll.indices) range allocation
for (i in 0..coll.size): no allocation
for (el in coll): iterator allocation
coll.forEach: iterator allocation
To iterate an array without allocating extra objects you can use one of the following ways.
for-loop
for (e in arr) {
println(e)
}
forEach extension
arr.forEach {
println(it)
}
forEachIndexed extension, if you need to know index of each element
arr.forEachIndexed { index, e ->
println("$e at $index")
}
As far as I know the only allocation-less way to define a for loop is
for (i in 0..count - 1)
All other forms lead to either a Range allocation or an Iterator allocation. Unfortunately, you cannot even define an effective reverse for loop.
Here is an example of preparing a list and iterate with index and value.
val list = arrayListOf("1", "11", "111")
for ((index, value) in list.withIndex()) {
println("$index: $value")
}
Output:
0:1
1:11
2:111
Also, following code works similar,
val simplearray = arrayOf(1, 2, 3, 4, 5)
for ((index, value) in simplearray.withIndex()) {
println("$index: $value")
}
I'm using gcov to get code coverage for our project, but it frequently reports 50% conditional coverage for plain function calls. It doesn't make any difference if the function takes any parameters or returns any data or not. I'm using gcovr and Cobertura with Jenkins, but a simple gcov file gives the same result.
The actual tested code is attached below together with the stubbed functions, all in gcov format.
Any ideas why gcov threats these function calls as branches?
-: 146:/*****************************************************************************/
function _Z12mw_log_clearv called 2 returned 100% blocks executed 100%
2: 147:void mw_log_clear( void )
2: 147-block 0
-: 148:{
2: 149: uint8_t i = 0;
2: 150: uint8_t clear_tuple[EE_PAGE_SIZE] = { 0xff };
-: 151:
66: 152: for (i = 0; i < (int16_t)EE_PAGE_SIZE; i++)
2: 152-block 0
64: 152-block 1
66: 152-block 2
branch 0 taken 97%
branch 1 taken 3% (fallthrough)
-: 153: {
64: 154: clear_tuple[i] = 0xff;
-: 155: }
-: 156:
-: 157: /* Write pending data */
2: 158: mw_eeprom_write_blocking();
2: 158-block 0
call 0 returned 100%
branch 1 taken 100% (fallthrough) <---- This is a plain function call, not a branch
branch 2 taken 0% (throw) <---- This is a plain function call, not a branch
-: 159:
26: 160: for (i = 0; i < (RESERVED_PAGES_PER_PAREMETER_SET - POPULATED_PAGES_PER_PAREMETER_SET); i++)
2: 160-block 0
24: 160-block 1
26: 160-block 2
branch 0 taken 96%
branch 1 taken 4% (fallthrough)
-: 161: {
25: 162: if (status_ok != mw_eeprom_write(LOG_TUPLE_START_ADDRESS + i * EE_PAGE_SIZE, clear_tuple, sizeof(clear_tuple)))
25: 162-block 0
call 0 returned 100%
branch 1 taken 100% (fallthrough) <---- This is a plain function call, not a branch
branch 2 taken 0% (throw) <---- This is a plain function call, not a branch
25: 162-block 1
branch 3 taken 4% (fallthrough)
branch 4 taken 96%
-: 163: {
1: 164: mw_error_handler_add(mw_error_eeprom_busy);
1: 164-block 0
call 0 returned 100%
branch 1 taken 100% (fallthrough) <---- This is a plain function call, not a branch
branch 2 taken 0% (throw) <---- This is a plain function call, not a branch
1: 165: break;
1: 165-block 0
-: 166: }
-: 167:
24: 168: mw_eeprom_write_blocking();
24: 168-block 0
call 0 returned 100%
branch 1 taken 100% (fallthrough) <---- This is a plain function call, not a branch
branch 2 taken 0% (throw) <---- This is a plain function call, not a branch
-: 169: }
2: 170:}
2: 170-block 0
-: 171:
-: 172:/*****************************************************************************/
/*****************************************************************************/
void mw_eeprom_write_blocking(void)
{
stub_data.eeprom_write_blocking_calls++;
}
/*****************************************************************************/
void mw_error_handler_add(mw_error_code_t error_code)
{
EXPECT_EQ(error_code, stub_data.expected_error_code);
stub_data.registered_error_code = error_code;
}
/*****************************************************************************/
status_t mw_eeprom_write(
const uint32_t eeprom_start_index,
void *const source_start_address,
const uint32_t length)
{
stub_data.eeprom_write_start_index = eeprom_start_index;
stub_data.eeprom_write_length = length;
stub_data.eeprom_write_called = true;
EXPECT_NE(NULL, (uint32_t)source_start_address);
EXPECT_NE(0, length);
EXPECT_LE(eeprom_start_index + length, EEPROM_SIZE);
if (status_ok == stub_data.eeprom_write_status)
memcpy(&stub_data.eeprom[eeprom_start_index], source_start_address, length);
return stub_data.eeprom_write_status;
}
Solved!
Found the answer in this thread:
Why gcc 4.1 + gcov reports 100% branch coverage and newer (4.4, 4.6, 4.8) reports 50% for "p = new class;" line?
Seems like gcov reacted on some "invisible" exception handling code for these function calls, so adding "-fno-exceptions" to g++ made all these missing branches to disappear.