Frendli

Programming Language for CS1

Developer

Elle J

Category

Language

Release Year

2022

Java

Parser

AST

Interpreter

Frendli is an open-source general-purpose programming language designed around empirical data on difficulties and misconceptions held by novice programmers. It is intended for learning and teaching programming in introductory (CS1) courses.

The language is implemented with a custom recursive decent parser, interpreting each node of the AST as it's visited.

πŸ‘‰οΈ Frendli and its docs are in active development.

Frendli Code Snippets

Variables, Data Types, and Literals

// Variables

create age = 30
create price = 4.25
create isValid = true
create isOnline = false
create nickname = empty
change nickname = "Alex"

Control Flow

// Selection

create score = 5
create message = ""

if score > 10
change message = "Very Good"
otherwise if score > 5
change message = "Good"
otherwise
change message = "Bad"
// Bounded loop

create count = 0

repeat 5 times
change count = count + 1
display(send count)
// Unbounded loop

create max = 5
create count = 0

repeat while count < max
change count = count + 1
display(send count)

Functions

// Function

define add(accept a, b)
create result = a + b
return with result

create result = add(send 1, 2)
display(send result)

OOP

(paused feature, may be removed)

// Class

describe Point
has x
has y

define onNew(accept x, y)
change me.x = x
change me.y = y

define move(accept x, y)
change me.x = me.x + x
change me.y = me.y + y

create pointA = new Point(send 1, 2)
pointA.move(send 3, 4)

Purpose

Frendli was developed to address the frequent challenges experienced by novice students. Simply put, to create a friendlier language.

It is intended for use in the beginning stages of introductory programming courses, helping the student conceptualize and start programming with minimal friction, and thereafter transitioning early or mid-course to a different established language.

The syntactic and semantic design is based on published studies on novices in introductory programming courses at universities. The studies revealed numerous factors that can be exploited in language design to facilitate learning to program.

Frendli was originally developed as part of the thesis Designing an Introductory Programming Language Based on Studies on Novices.

Goals

Frendli is novice-oriented and centers around three main goals which are:

1. Be a low barrier to entry

Subgoal: Be easy to use and understand.

Since first-time programmers are the intended primary users of the language, lowering the barrier of entry and alleviating initial hurdles is important.

This means*:

  • Producing fewer encountered difficulties and misconceptions.
  • Minimizing interference of syntax and time fixing syntax errors.
  • Being more intuitive and less ambiguous.
  • Having consistency between syntax and semantics.
  • Being less challenging for non-native English speakers.

2. Facilitate conceptualization

Subgoal: Illustrate what constructs do through their syntax.

Misconceptions are very common among novices and often arise from the syntax itself (see article). Frendli's goal is therefore to help the user conceptualize.

This means*:

  • Having syntax that is more self-explanatory.

3. Be universally transitional

Subgoal: Be a useful tool for teaching introductory programming and concepts.

Allowing easier transition into multiple (i.e. universally) languages not only helps the student, but provides a realistic alternative for more educational institutions in terms of efficiently incorporating it into their existing programs, especially in combination with being useful for teaching.

This means*:

  • Not forcing the use of entity terminology specific to Frendli.
  • Having less syntactic and conceptual conflict with the other languages.
  • Being less programming language dependent for reading and reasoning.
  • Being pedagogically easier to focus on fundamental concepts.

* Compared to other languages used in introductory university courses.

General Characteristics

  • Text-based
  • High-level
  • General-purpose
  • Dynamically typed
  • Imperative
  • Optionally object-oriented
    • (paused feature, may be removed)
  • Interpreted

Features (v0.1)

Implemented features are marked as completed.

  • βœ… Data types
    • βœ… number (-2, 0, 10.5)
    • βœ… text ("Hello Frendli Programmer!")
    • βœ… boolean (true, false)
    • βœ… empty
  • βœ… Single-line comments (//)
  • βœ… Lexical scope
  • βœ… Variables
    • βœ… Declaration (create)
    • βœ… Assignment (change)
    • βœ… Dynamic typing
  • βœ… Operators
    • βœ… Assignment
      • βœ… Bind to (=)
    • βœ… Comparison
      • βœ… Less than (<)
      • βœ… Less than or equal to (<=)
      • βœ… Greater than (>)
      • βœ… Greater than or equal to (>=)
      • βœ… Equal to (equals)
      • βœ… Not equal to (unequals)
    • βœ… Logical
      • βœ… Conjunction (and)
      • βœ… Disjunction (or)
      • βœ… Negation (not)
    • βœ… Arithmetic
      • βœ… Addition (+)
      • βœ… Subtraction (-)
      • βœ… Negation (-)
      • βœ… Multiplication (*)
      • βœ… Division (/)
    • βœ… Text
      • βœ… Concatenation (+)
    • βœ… Precedence altering
      • βœ… Grouping (())
  • βœ… Control
    • βœ… Selection
      • βœ… if
        • βœ… otherwise if
        • βœ… otherwise
    • βœ… Loop
      • βœ… Bounded (repeat times)
      • βœ… Unbounded (repeat while)
  • βœ… Functions
    • βœ… Declaration and definition (define)
      • βœ… Accept parameters ((accept a, b, c))
      • βœ… Return without explicit return value (return)
      • βœ… Return with explicit return value (return with)
    • βœ… Call a function (())
      • βœ… Send arguments ((send a, b, c))
    • βœ… Closure
  • β­• OOP (paused feature, may be removed)
    • β­• Classes / user-defined types
      • β­• Declaration and definition (describe)
      • β­• Fields
        • β­• Declaration (has)
      • β­• Methods
        • βœ… Declaration and definition (define) (same as function)
        • β­• Constructor (onNew)
        • β­• Self reference (me)
        • βœ… Call a method (same as function)
      • β­• Single public inheritance (inherit)
        • β­• Parent reference (parent)
    • β­• Instances
      • β­• Instantiation (())
      • β­• Member (field or method) access (.)
  • βœ… Standard library
    • βœ… Functions
      • βœ… Output text to user (display)
      • βœ… Get milliseconds since epoch (time)
  • β­• Error reporter
    • βœ… Initial error messages (not yet β€œfriendlified”)
    • β­• Provide highly user-friendly (and novice-friendly) error messages
  • β­• REPL (interactive prompt)
    • β­• Provide separate grammar to allow omitting the newline character

Future Additions

Near to Intermediate-term

  • Array/list data structure
  • Extended standard library
    • I/O operations (e.g. reading keyboard input)
    • Data type checking
    • Data type casting
  • Arithmetic operators (e.g. modulus)
  • Control statements (e.g. terminate execution of a loop)

Runnable Sample Program

Below is a small program that is runnable using the current implementation.

  1. When timeCount() is invoked, it will time how long it takes to count from 0 to target in increments of step, while displaying the current count.
  2. If the arguments sent were valid, evaluate() is invoked to evaluate if we guessed the right number of seconds it took to count.
// Time visibly counting to a target
define timeCount(accept target, step)
if target <= 0 or step <= 0
display(send "Numbers must be positive.")
return

create count = 0
create startTime = time()

repeat while count < target
change count = count + step
display(send count)

create endTime = time()

return with (endTime - startTime) / 1000

// Evaluate a guess
define evaluate(accept guess, actual)
if guess equals actual
display(send "Correct.")
otherwise if guess < actual
display(send "Too low.")
otherwise
display(send "Too high.")

// Start the count
create target = 100
create step = 1
create result = timeCount(send target, step)

// Guess the number of seconds
if result unequals empty
create guess = 0.01
evaluate(send guess, result)