Wiki
Version 1 (modified by hopscc, 10 years ago)

--

Cobra Code Examples

Some highlights of Cobra code and syntax ( on .Net)

Here are the cobra code samples for the same items for a  VB and C# comparison.

Program Structure


#use System  # already defaulted in 

namespace Hello 
    class HelloWorld 
        def main is shared
            name = "Cobra"

            args = CobraCore.commandLineArgs
            # See if an argument was passed from the command line
            # (first arg is progname)
            if args.count == 2
                name = args[1]

            Console.writeLine("Hello, " + name + "!")
            #print "Hello, [name]!"

Comments


# Single line comment
/# Multiple
    lines  #/
    
# <summary>XML comments on single line</summary>
/# <summary>XML comments on multiple lines</summary> #/

Data Types

These are as per .Net (using .Net naming rather than C#)

# Value Types
    bool
    uint8   # byte
    char
    int16, uint16, int, uint, int64, uint64        # short, ushort, int, uint, long, ulong
    float, float32, float64     #float, double
    Decimal
    DateTime   #(not a built-in C# type)
    Struct
    Enum (enumerations)

#Reference Types
    Object
    String
    arrays
    Sigs/Delegates

#Initializing  ( the explicit typing (clause 'as ????' ) is optional, types are inferred from initialisation)
        correct as bool = true
        b as uint8 = 0x2A   # hex
        person as Object? = nil
        name as String = "Dwight"
        grade as char = c'B'
        today as DateTime= DateTime.parse("12/31/2010 12:15:00 PM")
        amount as decimal = 35.99 
        gpa as float = 2.9f
        pi as float64 = 3.14159265_f64
        lTotal as int64 = 123456_i64
        sTotal as int16  = 123
        usTotal as uint16 = 123
        uiTotal as uint  = 123   # or 123u
        ulTotal as uint64 = 123   # or 123u64

        #Nilable Types
        x as int? = nil

#Anonymous Types
# Havent worked out how Cobra handle these examples yet...
#var stu = new {Name = "Sue", Gpa = 3.5}
#var stu2 = new {Name = "Bob", Gpa = 2.9}   # no Key equivalent

#Implicitly Typed Local Variables
        s = "Hello!"
        nums = @[ 1, 2, 3 ] #init from array literal
        hero = SuperHero("Batman")

#Type Information
        x as int? = 0  # Nilable int
        Console.writeLine(x.getType)        # Prints System.Int32
        Console.writeLine(sharp'typeof(int)')      # Prints System.Int32
        Console.writeLine(x.getType.name)   # prints Int32

#Type Conversion / Casting
        d = 3.5f
        i = Convert.toInt32(d)     # Set to 4 (rounds)
        i1 as int = d to int       # set to 3 (truncates decimal)   

Constants

const MAX_STUDENTS as int = 25

# Can set to a const or var; may be initialized in a constructor
var MIN_DIAMETER as float is readonly= 4.93f 

Enumerations

enum Action 
    Start, Stop, Rewind, Forward

enum Status 
    Flunk = 50
    Pass = 70 
    Excel = 90

a = Action.Stop
if a <> Action.Start
    Console.WriteLine(a + " is " + (int) a);    # Prints "Stop is 1"

Console.writeLine(Status.Pass to int) # Prints 70
Console.writeLine(Status.Pass)        # Prints Pass

Operators


#Comparison
==  <  >  <=  >=  <>

# Arithmetic
+  -  *  /
%  (mod)
/  (integer division if both operands are ints)
Math.Pow(x, y)

#Assignment
=  +=  -=  *=  /=   %=  &=  |=  ^=  <<=  >>= 
# +=1  -=1  # ++, -- No post increment/decrement

#Bitwise
&   |   ^   ~   <<   >>

#Logical
and   or  not 
#Note: and and or perform short-circuit logical evaluations

#String Concatenation
+

Choices


# Nil-coalescing operator
x = y ? 5   # if y != null then x = y, else x = 5

# non nil coalescing
x = y ! y.parseIt   # if y nil x = nil else x = y.parseIt()

# Ternary/Conditional operator
greeting = if(age < 20, "What's up?", "Hello")

if age < 20
    greeting = "What's up?"
else
    greeting = "Hello"

# Multiple statements must be indented following
if x <> 100 and y < 5
    x *= 5
    y *= 2


# braces not needed around condition expressions unless complicated
if x > 5
    x *= y
else if x == 5 or y % 2 == 0
    x += y
else if x < 10
    x -= y
else
     x /= y

# alternatively (1 liners)
if x > 5, x *= y
else if x == 5 or y % 2 == 0, x += y
else if x < 10, x -= y
else, x /= y

# indented action blocks, breaks not needed
case color  #   Must be integer, character, enumeration or string
  on "pink" or "red" #constants
    r++ 
  on "blue"
    b++
  on "green"
    g++ 
  else
    other++        

# 1 liners
case color                     
  on 'pink' or  'red', r++ 
  on 'blue',  b++
  on 'green', g++ 
  else,    other++        

Loops

# re-test Loops:  

# no "until" keyword
while c < 10
    c += 1


for c in 2 : 11 : 2  # start: stop : step
    Console.writeLine(c)
    #print c

#Post-test Loop:
post while c < 10
    c += 1


# Array or collection looping
names = {"Fred", "Sue", "Barney"}
for s in names
    Console.writeLine(s)
    # print s


# Breaking out of loops
i = 0
while true
    if i == 5
        break
    i += 1

# Continue to next iteration
for i in 0 : 5 
    if i < 4
        continue
    print i       #same as Console.writeLine(i)   # Only prints 4
  

Arrays

#Preference is for (typed) collections rather than arrays

nums as int[] = @[1, 2, 3]
for  i in 0 : nums.length
  Console.writeLine(nums[i])


# 5 is the size of the array
names as String[]= String[](5)
names[0] = 'David';
names[5] = "Bobby";   # Throws System.IndexOutOfRangeException

# Add two elements, keeping the existing values
Array.resize(ref names, 7)

# multi dim and jagged arrays not well supported (use Collections)
twoD = sharp'new float[rows, cols]'
twoD[2,0] = 4.5f 

jagged as int[][] = sharp'new int[3][] { new int[5], new int[2], new int[3] }'
jagged[0][4] = 5 

As a collection

nums = [1, 2, 3]
for i in 0 : nums.count
  print nums[i]

# 5 is the size of the array
names = List(5)
names[0] = "David";
names[5] = "Bobby";   # Throws System.IndexOutOfRangeException

Functions


    # Pass by value (in, default), in/out reference (inout), and reference (out)
    def testFunc(x as int, y as inout int, z as out int)
        x += 1  
        y += 1
        z = 5

    # Accept variable number of arguments
    def sum(nums as vari int) as int
        sum as int = 0
        for i in nums
            sum += i
        return sum
    
    def sayHello(name as String, prefix = "")
        Console.writeLine("Greetings, " + prefix + " " + name)

    def main
    
        a = 1
        b = 1 
        c as int  # c doesn't need initializing
        .testFunc(a, inout b, out c)
        Console.writeLine("{0} {1} {2}", a, b, c)  # 1 2 5
                assert c == 5 and b == 2

        total = .sum(4, 3, 2, 1)   # returns 10
        assert total == 10
        
        
        .sayHello("Strangelove", "Dr.")
        .sayHello("Mom") 

Strings


# Escape sequences
# \r    # carriage-return
# \n    # line-feed
# \t    # tab
# \\    # backslash

# Can use either " or ' to delimit String literals
# preference is for ' unless string contains ', then use "

# String concatenation
school = "Harding\t"
school = school + "University"   # school is "Harding (tab) University"
school += "University"   # Same thing
school += 'University'   # Same thing

# Chars
letter = school[0]              # letter is H
letter = 'Z'                    # letter is Z
letter = Convert.toChar(65)     # letter is A
letter = 65 to Char             # same thing
word = school.toCharArray       # word holds Harding

# String literal
string filename = r'c:\temp\x.dat'   # Same as "c:\\temp\\x.dat"

# String comparison
mascot = 'Bisons' # or mascot = "Bisons"
if mascot == "Bisons"    # true
if mascot.equals('Bisons')   # true
if mascot.toUpper.equals('BISONS')   # true
if mascot.compareTo('Bisons') == 0  # true

# String matching - No Like equivalent, use Regex


# Substring
s = mascot.substring(2, 3)     # s is "son"

# Replacement
s = mascot.replace('sons', 'nomial')     # s is "Binomial"

# Split
names = 'Michael,Dwight,Jim,Pam'
parts = names.split(','.toCharArray())   # One name in each slot
#or
parts = names.split([ c',']) 

# Date to string
DateTime dt = DateTime(1973, 10, 12)
s = dt.toString('MMM dd, yyyy')     # Oct 12, 1973

# int to string
x = 2
y = x.toString()     # y is "2"
# string to int
x = Convert.toInt32('-5')     # x is -5

# Mutable string
buffer = System.Text.StringBuilder('two ')
buffer.append('three ')
buffer.insert(0, 'one ')
buffer.replace('two', 'TWO')
Console.writeLine(buffer)     # Prints "one TWO three"

Regular Expressions

use System.Text.RegularExpressions


        # Match a string pattern
        r = Regex(r'j[aeiou]h?. \d:*', RegexOptions.IgnoreCase | RegexOptions.Compiled)
        if r.match('John 3:16').success   # true
            Console.writeLine("Match")


        # Find and remember all matching patterns
        s = 'My number is 305-1881, not 305-1818.'
        r = Regex(r'(\\d+-\\d+)')
        # Matches 305-1881 and 305-1818
        m as Match = r.match(s) 
        while m.success 
            #Console.writeLine("Found number: " + m.groups[1].toString + " at position " + m.groups[1].index.toString)
            print 'Found number: [m.groups[1]] at position [m.groups[1].index]'
            m = m.nextMatch to !


        # Remember multiple parts of matched pattern
        r = Regex(r'(\d\d):(\d\d) (am|pm)')
        m = r.match("We left at 03:15 pm.")
        if m.success
            Console.writeLine("Hour: " + m.groups[1].toString)       # 03
            Console.writeLine("Min: "  + m.groups[2].toString)       # 15
            Console.writeLine("Ending: " + m.groups[3].toString)   # pm

        # Replace all occurrances of a pattern
        r = Regex(r'h\\w+?d', RegexOptions.IgnoreCase)
        s = r.replace("I heard this was HARD!", "easy")   # I easy this was easy!

        # Replace matched patterns
        s = Regex.replace('123 < 456', r'(\d+) . (\d+)', '$2 > $1')   # 456 > 123

        # Split a string based on a pattern
        names = 'Michael, Dwight, Jim, Pam'
        r = Regex(r',\s*')
        parts = r.split(names)   # One name in each slot 

Exceptions


# Throw an exception
up = Exception('Something is really wrong.')
throw up  # ha ha

# Catch an exception
try  
    y = 0
    x = 10 / y
catch ex as Exception    # Argument is optional, no "When" keyword 
    Console.writeLine(ex.message)
finally 
     Microsoft.VisualBasic.Interaction.beep
 

Namespaces

namespace Harding.Compsci.Graphics
  ...

# or

namespace Harding 
    namespace Compsci 
        namespace Graphics
      ...

use Harding.Compsci.Graphics 

Classes and Interfaces


## Access Modifiers
    public  # default
    private
    internal
    protected
    protected internal

#Class Modifiers
    abstract
    shared

#Method Modifiers
    abstract
    shared
    virtual #default

#No Module equivalent - just use static class

# Partial classes
class Competition is partial
  ...

# Inheritance
class FootballGame inherits Competition 
  ...


# Interface definition
interface IAlarmClock 
  def ring  # public returns void by default
  pro currentDateTime as DateTime from var
}

# Extending an interface 
interface IAlarmClock inherits IClock 
  ...
}


# Interface implementation
class WristWatch implements IAlarmClock, ITimer 

    def ring
        Console.writeLine('Wake up!')

  pro triggerDateTime as DateTime from var
  ...

Constructors and Destructors

class SuperHero inherits Person 

    var powerLevel as int is private
    var name as String is private


    # Default constructor
    cue init 
        .powerLevel = 0
        .name = 'Super Bison'

    cue init(powerLevel as int)
        base.init('Super Bison')   # Call other constructor
        .powerLevel = powerLevel 

    cue init(name as String)
        base.init(name)      # Call base classes' constructor
        .name = name

    cue init is shared
        # Static constructor invoked before 1st instance is created

    cue finalize
        # Destructor implicitly creates a Finalize method

Using Objects


hero as SuperHero? = SuperHero()

# No "With" but can use property initializers
hero = SuperHero(name = "SpamMan", powerLevel = 3) 

hero.defend("Laura Jones")
SuperHero.rest   # Calling static method


hero2 = hero   # Both reference the same object
hero2.name = 'WormWoman'
Console.writeLine(hero.name)   # Prints WormWoman

hero = nil    # Free the object

if hero == nil # or    if not hero
    hero = SuperHero()

obj as Object = SuperHero() 
if obj inherits SuperHero
    Console.writeLine("Is a SuperHero object.")

# Mark object for quick disposal
using reader as StreamReader = File.openText("test.txt") 
  line as String?
  while (line = reader.readLine) <> nil
    Console.writeLine(line)

Structs

struct Student 
    var name as String
    var gpa as float

    cue init(name as String, gpa as float)
        .name = name
        .gpa = gpa

stu = Student("Bob", 3.5f)
stu2 = stu  

stu2.name = "Sue"
Console.writeLine(stu.name)    # Prints Bob
Console.writeLine(stu2.name)   # Prints Sue

Properties



# Auto-implemented properties
pro name as String from var
get size as int from var #   Set default value in constructor

# Traditional property implementation
var name as String is private # private backing variable
#or
#var __name as String #private
#var _name as String  #protected


pro Name as String
    get 
        return .name
        # return __name
    set
        .name = value
        #__name =value

# Read-only property
var powerLevel as int is private # private backing variable
get powerlevel from var

#alternatively 
var __powerLevel = 0 # inferred as type int, private
get powerlevel from var

# Write-only property
var height as double is private # private backing variable
set height as double
    .height = if(value < 0,  0, value)

Generics

# Enforce accepted data type at compile-time
numbers = List<of int>()
numbers.add(2)
numbers.add(4)
displayList<of int>(numbers)

# Function can display any type of List
def displayList<of T>(List<of T> list)
    for item as T in list
        Console.writeLine(item)

# Class works on any data type
class SillyList<of T> 
    list as T[] = T[](10)
    rand as Random = Random()

    public void add(item as T)
        list[rand.next(10)] = item

    public getItem as T
        return list[rand.next(10)]
}

# Limit T to only types that implement IComparable
def maximum<of T>(items as vari T) where T must be IComparable<of T> 
    max as T = items[0]
    for item in items
        if item.compareTo(max) > 0
            max = item
    return max

Delegates and Lambda Expresssions

sig HelloDelegate(s as String) # returns void

def sayHello(s as String) 
    Console.writeLine('Hello, ' + s)

# C# 1.0 delegate syntax with named method
hello as HelloDelegate = ref .sayHello
hello('World')   # Or hello.Invoke('World')

# C# 2.0 delegate syntax with anonymous method
# method body indented on lines following do(args)
hello2 as HelloDelegate = do(s as String)
    Console.WriteLine('Hello, ' + s)

hello2("World")

# C# 3.0 delegate syntax with lambda expression
HelloDelegate hello3 as HelloDelegate = do(s as string)=Console.writeLine('Hello, ' + s) 
hello3("World")

# Use Func<in T, out TResult> delegate to call Uppercase
convert as Func<of String, of String> = ref .uppercase
Console.writeLine(convert("test"))

def uppercase(s as String)
  return s.toUpper

# Declare and invoke Func using a lambda expression
Console.WriteLine( Func<of int, of int>do(num as int) = num + 1)(2))

# Pass lamba expression as an argument
TestValues(do(x, y) = x % y == 0)

void TestValues(Func<of int, of int, of bool> f)
  if f(8, 4)
    Console.writeLine("true")
  else
    Console.writeLine("false")

Events

sig MsgArrivedEventHandler(message as String)

event MsgArrivedEvent as MsgArrivedEventHandler 


# listen EVENT_NAME, METHOD_NAME
listen MsgArrivedEvent, MsgArrivedEventHandler(.my_MsgArrivedEventCallback)
raise MsgArrivedEvent, "Test message"    # Throws exception if obj is null
#ignore EVENT_NAME, METHOD_NAME
ignore MsgArrivedEvent, MsgArrivedEventHandler(.my_MsgArrivedEventCallback)


using System.Windows.Forms

myButton = Button() 
listen myButton.click, System.EventHandler(ref .myButton_Click)

def myButton_Click(sender as Object, e as System.EventArgs )
    MessageBox.show(this, "Button was clicked", "Info",
        MessageBoxButtons.OK, MessageBoxIcon.Information)

LINQ

TBI

Attributes

# Attribute can be applied to anything
class IsTestedAttribute inherits Attribute
    pass
    
# Attribute can only be applied to classes or structs
class AuthorAttribute inherits Attribute 
    has AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)

    pro name as String from var
    pro version as int from var

    cue init(name as String )
        .name = name;
        .version = 0;
    }
}

class Shape 
    has Author("Sue", version = 3)

    def move 
        has IsTested 
        // Do something...
    

Console I/O

    
Console.write("What's your name? ")
name as String = Console.readLine
Console.write('How old are you? ')
age as int = Convert.toInt32(Console.readLine)
Console.writeLine("{0} is {1} years old.", name, age)
# or
Console.writeLine(name + " is " + age + " years old.")

c as int = Console.read  # Read single char
Console.writeLine(c)    # Prints 65 if user enters "A"

# alternatively

print "What's your name? " stop
name = Console.readLine
print 'How old are you? ' stop
age  = Convert.toInt32(Console.readLine)
print '[name] is [age] years old.'
# or
print String.format('{0} is {1} years old.', name, age)

c as int = Console.read  # Read single char
print c                  # Prints 65 if user enters "A"

File I/O

#use System.IO # already autoloaded

# Write out to text file
writer as StreamWriter  = File.createText(r'c:\myfile.txt')
writer.writeLine('Out to file.')
writer.close

# Read all lines from text file
reader as StreamReader  = File.openText(r'c:\myfile.txt')
line = reader.readLine
while line 
    Console.writeLine(line)
    line = reader.readLine
reader.close

# Write out to binary file
str as String = "Text data"
num = 123
binWriter = BinaryWriter(File.openWrite(r'c:\myfile.dat'))
binWriter.write(str)
binWriter.write(num)
binWriter.close

# Read from binary file
binReader = BinaryReader(File.openRead(r'c:\myfile.dat'))
str = binReader.readString
num = binReader.readInt32
binReader.close

Return to wiki:WikiStart