A CIL Tutorial - Department of Computer Science - ETH Zürich

A CIL Tutorial - Department of Computer Science - ETH Zürich A CIL Tutorial - Department of Computer Science - ETH Zürich

29.01.2014 Views

CHAPTER 14. IMPLEMENTING A SIMPLE DSL 116 let hasArgAttr : attributes → bool = hasAttribute argStr let hasAssertAttr : attributes → bool = hasAttribute assertStr let hasMandatoryAttr : attributes → bool = hasAttribute mandatoryStr The functions isArgType, and isMandatoryType return true when their argument types have the indicated attributes. let isArgType (t : typ) : bool = t | > typeAttrs | > hasArgAttr let isMandatoryType (t : typ) : bool = t | > typeAttrs | > hasMandatoryAttr The function getAssertAttr returns the attribute parameter when the type has a "ciltut assert" attribute, and otherwise throws an exception. let getAssertAttr (t : typ) : attrparam = match filterAttributes assertStr (typeAttrs t) with | [Attr( , [ap])] → ap | → E.s (E.error "Malformed %s attribute: %a" assertStr d type t) The function string of exp extracts a string literal from an expression and returns it as an OCaml string. If the expression is NULL, it returns the empty string. If the expression is not a string, it raises an exception. We'll use it to extract structure elds for the argument type. let rec string of exp (e : exp) : string = match e with | Const(CStr s) → s | z when z = zero → "" | CastE( , e) → string of exp e | → E.s (E.error "Expected string literal: %a" d exp e) The function name of argname extracts the name of the argument from the name of the instance of the argument description structure. let name of argname (s : string) : string = if S.length s < 8 then E.s (E.error "Invalid argument name: %s" s); S.sub s 8 (S.length s − 8) Since we're using attributes to express the assertions about arguments, we'll need a few functions from Chapter 8 that we'll use to compile the attribute parameters. The function req of exp extracts the attrparam for an argument assertion from a CastE expression, and compiles it using T.exp of ap. The context c holds all of the global variables, so the assertion can also refer to other command line arguments.

CHAPTER 14. IMPLEMENTING A SIMPLE DSL 117 module T = Tut8 let req of exp (c : T.ctxt) (loc : location) (e : exp) : exp = match e with | CastE(t, z) when z = zero → t | > getAssertAttr | > T.exp of ap c loc | → one The command line arugment specication is the in form of a static initializer on a global variable. We'll iterate through the list of global variable declarations looking for global variable denitions (i.e. GVars) whose types have the ciltutarg attribute. The function handle field looks at one eld of the static initializer on the GVar, and uses it to ll in a eld of the argument type we dened above. let handle field (c : T.ctxt) (loc : location) (a : argument) (off : offset) (ini : init) (t : typ) () : unit = match off, ini with | Field(f, NoOffset), SingleInit e → begin match f.fname with | "short form" → a.argShort ← string of exp e | "help text" → a.argHelp ← string of exp e | "def" → a.argDef ← e; a.argType ← f.ftype; a.argVi ← makeGlobalVar a.argName a.argType | "requires" → a.argReq ← req of exp c loc e | "format" → a.argFmt ← string of exp e | "has opt" → a.argOption ← e = one | → E.s(E.bug "malformed arg struct") end | → E.s(E.bug "Unexpected initializer in argument of global") The function argument of global looks at one global, g, to determine whether it is a command line argument sepcication, i.e. whether it is a GVar with isArgType returning true. If so, it makes a new argument, lls in a few of the elds that can be determined immediately, like the name of the argument, and calls iterCompound. iterCompound iterates over the elds of the static initializer using the function handle field that we just dened. iterCompound is dened in tututil.ml. It is based on foldLeftCompound from the CIL library. let argument of global (c : T.ctxt) (g : global) : argument list = match g with | GVar(vi, {init = Some(CompoundInit(t, ini))}, loc) when isArgType vi.vtype → begin let a = makeArgument () in

CHAPTER 14. IMPLEMENTING A SIMPLE DSL 117<br />

module T = Tut8<br />

let req <strong>of</strong> exp (c : T.ctxt) (loc : location) (e : exp) : exp =<br />

match e with<br />

| CastE(t, z) when z = zero →<br />

t | > getAssertAttr | > T.exp <strong>of</strong> ap c loc<br />

| → one<br />

The command line arugment specication is the in form <strong>of</strong> a static initializer on a global variable.<br />

We'll iterate through the list <strong>of</strong> global variable declarations looking for global variable denitions<br />

(i.e. GVars) whose types have the ciltutarg attribute. The function handle field looks at one<br />

eld <strong>of</strong> the static initializer on the GVar, and uses it to ll in a eld <strong>of</strong> the argument type we dened<br />

above.<br />

let handle field (c : T.ctxt) (loc : location) (a : argument)<br />

(<strong>of</strong>f : <strong>of</strong>fset) (ini : init) (t : typ) ()<br />

: unit<br />

=<br />

match <strong>of</strong>f, ini with<br />

| Field(f, NoOffset), SingleInit e → begin<br />

match f.fname with<br />

| "short form" → a.argShort ← string <strong>of</strong> exp e<br />

| "help text" → a.argHelp ← string <strong>of</strong> exp e<br />

| "def" → a.argDef ← e;<br />

a.argType ← f.ftype;<br />

a.argVi ← makeGlobalVar a.argName a.argType<br />

| "requires" → a.argReq ← req <strong>of</strong> exp c loc e<br />

| "format" → a.argFmt ← string <strong>of</strong> exp e<br />

| "has opt" → a.argOption ← e = one<br />

| → E.s(E.bug "malformed arg struct")<br />

end<br />

| → E.s(E.bug "Unexpected initializer in argument <strong>of</strong> global")<br />

The function argument <strong>of</strong> global looks at one global, g, to determine whether it is a command<br />

line argument sepcication, i.e. whether it is a GVar with isArgType returning true. If so, it makes<br />

a new argument, lls in a few <strong>of</strong> the elds that can be determined immediately, like the name <strong>of</strong> the<br />

argument, and calls iterCompound. iterCompound iterates over the elds <strong>of</strong> the static initializer<br />

using the function handle field that we just dened. iterCompound is dened in tututil.ml. It<br />

is based on foldLeftCompound from the <strong>CIL</strong> library.<br />

let argument <strong>of</strong> global (c : T.ctxt) (g : global) : argument list =<br />

match g with<br />

| GVar(vi, {init = Some(CompoundInit(t, ini))}, loc)<br />

when isArgType vi.vtype → begin<br />

let a = makeArgument () in

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!