Product Documentation
Cadence SKILL IDE User Guide
Product Version IC23.1, August 2023

SKILL Lint Features

Listed below are some of the SKILL Lint features.

Check the Number of Function Arguments

SKILL Lint checks that the number of arguments passed to a function is correct by verifying it against a previously-known definition of the function from a previous SKILL Lint session or a previous declaration. SKILL Lint delays checking the number of arguments until it finds the procedure definition.

If a procedure is used in a file before it is defined in the same file and the number of arguments to the procedure changes, it may be necessary to run SKILL Lint twice to get accurate results because the first run will use the previous declaration of the procedure.

Check Function and Global Variable Prefixes

Functions and global variables used in SKILL code are expected to be prefixed with a suitable string. You type these strings in the Package Prefixes field on the Lint Options form.

By default, strict checking is applied only to the global variables, while functions and Cadence’s prefixes are checked by specification.

The naming policy for functions and global variables is as follows:

You can turn off strict checking by disabling the STRICT message such that SKILL Lint checks only global variables beginning with a specified prefix.

Check SKILL Operators

SKILL Lint reports the SKILL operators used in the SKILL code. The following operators are supported in SKILL:

Check Redefinition of Write-protected Functions and Macros

SKILL Lint reports an error if the input name of an expression, defun, defmacro, mprocedure, nprocedure, or procedure is the name of a write-protected function or macro. For example, SKILL Lint will report an error for the following code because lindex is a write-protected function:

procedure( lindex(@optional (input1 "hello") (input2 "hi") )

     printf("\n%s %s" input1 input2)
)

Check Files Based on the Extension of the Input File (*.il/ *.ils/ *.scm)

SKILL Lint performs SKILL or SKILL++ language checks based on the extension, .il, .ils, or .scm of the input file for sklint. If the extension of the input file is .il, SKILL Lint applies SKILL language checks and if the extension of the input file is .ils, SKILL Lint applies SKILL++ language checks. It also applies SKILL++ language checks for the files with the extension .scm.

For example, SKILL Lint will report errors if the Scheme code displayed below is included in a file with extension .il.

defun( f1 (a b)
    let( (f (lambda((x) x*x)) )
     (f a+b)
)

Execute Code Blocks Placed Inside inSkill() and inScheme()

Before describing the following feature, it is important to reiterate that in the SKILL programming environment, Scheme mode describes SKILL++ code that is saved in a file with the .ils extension or enclosed in the inScheme() function. Similarly, SKILL mode describes SKILL code saved in a file with .il extension or enclosed in the inSkill() function.

Starting from IC6.1.6, SKILL Lint executes source code placed in the inScheme() function as SKILL++ language code even if the code is placed in a file with extension *.il. For example, SKILL Lint executes the following Scheme code correctly even though it is placed inside a file with extension .il

(let (v1 v2)
    v1 = v2 = 0
    (inScheme vf = (lambda () 'some_value))
) ; "vf" global Scheme function is defined inside inScheme() block

SKILL Lint understands the code (in Bold) as SKILL++ or Scheme code. In this example, vf is considered a Scheme function and not as a symbol.

Consider the following example where the code is placed inside a file with extension .ils

(let (v1 v2)
    v1 = v2 = 0
    (inSkill vf = (lambda () 'some_value))
) ; "vf" global Scheme function is defined inside inScheme() block

SKILL Lint understands the code (in Bold) as SKILL code. In this example, SKILL Lint will report errors because the expression related to vf function is in basic SKILL, which does not support local functions.

Check For Matching Global and Local Variable Names

SKILL Lint allows the name of a local variable to match that of a global variable and does not report the variable as being used before definition in a let assignment. In the example below, the name VAR has been used for both local and global variables.

(defvar VAR)
(defun ListGen (n)
(let ( (VAR (cons n VAR)) )
(info "The value of local variable VAR: %L\n" VAR)
(setq VAR (if (plusp n) (ListGen (sub1 n)) (cdr VAR)))
)
)
(info "Global variable VAR before function call: %L\n" VAR)
(info "Function call result: %L\n" (ListGen 3))
(info "Global variable VAR after function call: %L\n" VAR)

After the lint run, the following output is printed in the CIW:

Global variable VAR before function call: nil
The value of local variable VAR: (3)
The value of local variable VAR: (2 3)
The value of local variable VAR: (1 2 3)
The value of local variable VAR: (0 1 2 3)
Function call result: (1 2 3)
Global variable VAR after function call: nil

SKILL Lint understands that the variable VAR has been used as both global and local variable and does not report a warning on line 3 for it being used before available in a let assignment.

Support Local Functions in the Scheme Mode

In the Scheme mode (files with extension .ils), SKILL Lint recognizes local functions to be defined inside let, letseq, letrec, setq, flet, and labels blocks. This means that SKILL Lint allows local functions to be added as a list of valid variables and does not report them as unused variables even if they are not referenced or used. In the example shown below, f1 is a local function that is considered as a variable in the let block.

let( ( 
        ((f1 lambda(() println("f1()"))) 
        f1()

)

SKILL Lint applies special checks for Scheme code (files with extension .ils/.scm), if a function is defined as global function/procedure or if a local function is not defined inside the let, letseq, or letrec block.

Support Local Arguments in the Scheme Mode

In the Scheme mode, SKILL Lint recognizes local arguments defined via @key, @optional, and @aux options. For example, the following constructs are valid in the Scheme mode:

procedure( test1( arg11 @key (arg12 arg11) )
  (progn
  (println "In function test1")
   (assert arg11 == arg12)
  )
)
procedure( test2( arg21 @optional (arg22 arg21) )
    (progn
        (println "In function test2")
        (assert arg21 == arg22)
    )
)
(defun test11 ( arg111 @key (arg112 arg111) )
    (progn
        (println "In function test11")
        (assert arg111 == arg112)
    )
)
(defun test21 ( arg211 @optional (arg212 arg211) )
    (progn
        (println "In function test21")
        (assert arg211 == arg212)
    )
)
(inScheme
(defun smartlessp2 (arg1 arg2 @aux fn)
(cond
((and (numberp arg1) (numberp arg2)) (setq fn lessp) )
((and (symstrp arg1) (symstrp arg2)) (setq fn alphalessp) )
)
(if fn (fn arg1 arg2) -1)
)
(defvar A (list 3.0 1.0 "as" "df" 7))
(defvar B (list 1.0 5.0 "asd" "ca" "gh"))
(info "Test AUX:\n")
(foreach (itA itB) A B (info "%L < %L: %L\n" itA itB (smartlessp2 itA itB)))
)

Support Assignment of Functions as Variables in Scheme Mode

In the Scheme mode, SKILL Lint recognizes the use of local functions as variables that are defined inside the setq, getq, getd, putd, and defun and procedure blocks. See the following examples.

Example 1

This example shows the assignment of a variable to a function in a setq block. SKILL Lint considers the function smartless() as a local function in the Scheme mode.

defun( smartless (arg1 arg2)
 let( ( (fn nil) (ret nil) )
  if( (and (numberp arg1) (numberp arg2))
   then
    setq( fn lessp)
   else
    (when (and (symstrp arg1) (symstrp arg2))
     setq( fn alphalessp))
   )
   (when fn (setq ret (fn arg1 arg2)))
   ret
 )
)

Example 2

In this example, SKILL Lint considers the code ((getq obj1 funcObj) val) as a function call.

inScheme(
    defun( funcInst (x) x*x)
 defstruct( myStruct funcObj)
 defclass( testClass () ((intVar @initarg intVar)))
 let( (obj classObj obj1 (val 3))
         setq( obj (make_myStruct ?funcObj funcInst))
         setq( classObj (makeInstance 'testClass ?intVar obj))
        setq( obj1 (getq classObj intVar))
       info( "%L\n" ((getq obj1 funcObj) val))
 )
)

Example 3

In the following example, the function myFunc1() is defined as a local function that has one argument. SKILL Lint considers myFunc1 as a function and checks for the number of input arguments.

let( ()
     putd( 'myFunc1 (getd 'exp))
)
info( "Result: %L\n" (myFunc1 1 2))

Example 4

In this example, SKILL Lint considers exp() as a local function.

putd( 'myFunc2 exp)

Example 5

In the following example, smartlessp() is defined by using the defun() function and then assigned to a variable newFn. In the Scheme mode, SKILL Lint considers the variable, newFn, as a SKILL++ function. This new SKILL++ function, newFn, is further assigned to another variable func1. Therefore, SKILL Lint considers both newFn and func1 as SKILL++ functions.

defun( smartlessp (arg1 arg2)
    let( ( fn )
        cond(
            ((and (numberp arg1) (numberp arg2)) (setq fn lessp) )
            ((and (symstrp arg1) (symstrp arg2)) (setq fn alphalessp) )
        )
        (if fn (fn arg1 arg2) -1)
    )
)
newFn = smartlessp
func1 = newFn
info( "A: %L\n" (newFn (list 1) (list 2)))
info( "B: %L\n" (newFn 1 2))
info( "C: %L\n" (newFn "str2" "str3"))

Support of SKILL++ Features in SKILL Lint

SKILL Lint supports the following SKILL++ features:

Related Topics

SKILL Lint

Built-In Messages

Message Groups

SKILL Lint PASS/FAIL and IQ Algorithms


Return to top
 ⠀
X